1. 42

  2. 15

    … compared to C or C++.

    Compiling the D compiler (dmd), runtime and standard library on my machine takes 18s (I just measured). Granted, that doesn’t include cross compilers but ldc can handle cross-compilation. Building the compiler does have a dependency on gcc or clang though since there’s still some C++ code in there but nearly all of it is in D.

    Vendoring: the author mentions the practice of header-only libraries in C/C++. That’s a problem specific to those languages, and has everything to do with the lack of a package manager, nothing else. Hardly any other language has these problems, vendoring in Rust, D, etc. is just as easy as in Go. It’s usually not done because the versioning problems that plagued Go in the beginning never happened in the first place.

    In a post with 3 points on how Go’s tooling is great, 2 are common in basically any language that isn’t C or C++ (package management and vendoring), and the other (build speed) isn’t something that only it has.

    1. 6

      It’s not just “has package management”, it’s that it’s good. Which is actually a recent thing; before late 2018 vendoring was the only way to get reasonable behavior for production projects. There were a few different projects out there for doing version pinning, to save you from having to check in a vendor tree and manually manage everything, but they were all flawed in some way and all incompatible. But then go modules showed up and, surprisingly, did almost everything right, did it using only the core tools, and did it in a way that made pretty much every use-case easier, not just the Google-favored one. At this point I would recommend that other languages look to go get and go mod for inspiration, because compared to them, everyone else has warts.

      1. 3

        Apparently I need to look at this again, when I last used Go in earnest (mid-2017) everything was just a broken mess, and glide was the only thing that let us create a proper build at all. And yes, I did read about the “new” (has it been 1-2 years already?) discussion about mod and vendor, but I didn’t look into it.

        If it’s really that good.. reminds me of early Java (1.0-1.3?) where the myth that is was slow persisted for 10 or more years on…

        1. 4

          It’s very different, and much better.

          1. 4

            Yeah, we used Glide where I work. It was IMO the best available at the time, and it was almost tolerable, but had some huge annoyances, and was very slow. We switched everything to modules as soon as it was practical. All the weird workarounds in the build scripts are gone, builds are faster, it doesn’t flake out like glide sometimes did, and local dev instructions are now just “check out and go get”, no telling people to have glide installed, no explaining about GOPATH, etc.

          2. 3

            It’s not just “has package management”, it’s that it’s good.

            What is better about it than, say, cargo? Other than “it’s decentralised”, since I really don’t see how that’s an advantage.

            1. 4

              Haven’t used cargo. I find Rust interesting, but even as a polyglot I don’t have the brainspace for Rust and Go at the same time, and Go pays the bills.

              1. 3

                Russ Cox has written rather extensively about the rationale behind the Go modules (formerly “vgo”) design. The “The Principles of Versioning in Go” (bottom one) gives a good summary and comparison to tools like Cargo.

                It’s hard to summarize that article in a paragraph since the topic is a bit complex, but the tl;dr is that Go modules uses “minimal version selection” instead of a SAT solver. Modules declare “I need at least version X”, and Go will use the minimal version, instead of a SAT solver to try and figure out what the newest version we can use (…probably).

                I also think the UX of modules is pretty good, and it’s pretty fast (the amount of time I’ve spent waiting on bundler and dep to finish is not insignificant).

                1. 3

                  I read the article discussing the minimal version selection when it came out. I’m still not convinced. Maybe it’s a better default even, but I don’t see how it’s better than other package managers in practice.

                  1. 2

                    I don’t know whether or not it’s “better”; I guess time will tell. It’s certainly different. Personally, I think it’s a good thing that Go is trying something different and at least tries to improve, instead of “just copy what everyone else if doing”. That’s useful even if it turns out to be a dismal failure in a few years’ time (not that I expect that it will).

                2. 2

                  For me, the practical answer is that go modules are built directly into the language tooling and therefore “just work” as you use go. Because importing an external package requires using the full URL, you can simply add new imports to your go programs and run go build. This automatically finds your dependencies, downloads them, updates your go.mod file and then builds your program.

                  The entire experiences is almost completely invisible and friction-less. This isn’t to say cargo is bad (it’s not), but the experience here does feel like it is on a new level.

                  I was very skeptical of go mod and MVS when the initial posts were published, but using the tools in practice has been fantastic.

                3. -1

                  Can you really consider it good? There’s no concept of a central repo and it doesn’t even handle versioning.

                  1. 4

                    What do you mean with “doesn’t even handle versioning”? go get example.com/foo@v1.5.3 will get exactly that version?

                    The lack of a central repo is a feature, IMHO. It was addressed in this blog post as well so I won’t repeats the points.

                    1. 1

                      There’s no concept of a central repo

                      That’s very good.

                      and it doesn’t even handle versioning.

                      Sure it does, unless I misunderstand your meaning.

                4. 5

                  One thing that is commonly overlooked but a huge value add for me is the documentation generation, including godoc.org (gddo). Gddo isn’t included in the toolchain, but it’s a universal tool that can display documentation for any published package that is available to it. No need for the package author to know any special doxygen syntax or build CI infrastructure to publish documentation packages. Moreover, links automatically work across packages, which is relatively rare.

                  Lastly, the documentation is actually readable and usable; Python doc generators conventionally throw everything on the same page, and it’s nearly impossible to tell which class the __str__ method you’re looking at 10K lines down the page belongs to. The documentation for Go is broken down by packages and the relationship between a method and a “class” (“receiver” is the technical term) is always apparent without scrolling (contrast this with the Python requests docs https://twitter.com/weberc2/status/1182751312456376321). Also, because Go is statically typed, you aren’t at the mercy of package authors to document types (such documentation is abysmal in Python and JS, even for major mainstream packages).

                  1. 4

                    Since Go 1.5, Go is implemented in Go. It also has no external dependencies, so to build Go only a Go compiler is required.

                    This is huge, I agree. The ability to compile complex Go programs, including Go itself, without having to fall back to C or C++ is a game changer I feel.

                    1. 4

                      I agree the tooling is a key part of Go-in-practice, and Go up to now is almost an experiment in how far you can get improving everything else while the language is fixed.

                      A hidden key to many tools is the standard library’s Go parser, which lots of folks have used to write formatters, checkers, and other tools:

                      • goimports – like go fmt but notices if you need to add/remove a package import
                      • go vet, errcheck, and ineffasign – catches a bunch of common errors for you
                      • go lint, gosimple – offers more suggestions
                      • gocode and friends – type-aware autosuggest for editors
                      • gorename, go fix, eg – type-aware renaming, other automated edits

                      staticcheck will run a bunch of these for you and has integrations with editors, etc.

                      • Checks built into the language, e.g. no unused vars and packages and fewer implicit conversions than some langs
                      • Built-in test, benchmarking, profiling, tracing, race-condition-catching, and code-coverage tools
                      • Quick compiles help you test as you go
                      • “Batteries included” standard library that’s also pretty reliable and readable – crypto, compression, various encodings and file formats, networking including HTTP/2 and TLS, bignums, reflection, parsing Go…
                      • Basic package system with go get and godoc.org – dependency management has been tricky (inside Google, the company’s approach to deps mostly sidestepped the problems we have out in the real world), but what they initially shipped with did make it easy to get started quickly

                      It’s hard to convey the combined effect of all this, but I feel like it substantially reduces the distance from just getting something running to having something reasonably polished you can have some confidence in.

                      (And if your ecosystem is twice as good, that’s cool; I haven’t used everything. I imagine safe Rust, for example, is even better at the “you can be reasonably confident your thing really works” angle.)

                      I do think Go has reached a point where it’s time to address language warts more, and hope that everything comes together for that to start to happen effectively.

                      1. 0

                        GCC’s configure script wouldn’t even finish before Go was already built.