1. 23

  2. 14

    I don’t think this is a bad thing; the whole GOPATH/modules schism is confusing, especially for people new to the language; I’ve seen many people mix the workflows and run in to troubles. For those of us around since before modules were a thing it’s all pretty clear, but for everyone else it’s like joining in The Expanse in the middle of season 3, sasa ke?

    The big problem now is that a lot of resources are outdated; for example I typically recommend The Go Programming Language to people new to Go, and while the language itself is very compatible and all the code still works, the surrounding tooling changed so much people will have a hard time getting starting. At least in the current schism solution the book still works (even though it’s not the recommended approach). I hope they release a 2nd edition at some point.

    1. 3

      The $GOPATH stuff was one of the things that really irked me when I first learned to 8-10 years ago. It was bothersome enough I didn’t prioritize doing much real work with it.

      The first real production code I shipped uses the go modules work. Definitely glad to see it improve over time and reduce the quirkiness of the ecosystem.

      1. 3

        My impression last time I was trying to figure this out is also that all the Go official documentation is specified in the form of diffs, “here’s what we changed from the old system”, leading to lots of difficulties figuring out what I was supposed to do now.

        1. 14

          Yeah, this sounds about right. Maybe I should write a “Getting started with Go in 2021” post or some such, which gives a concise description in a way that doesn’t assume any prior knowledge. Perhaps something like this already exists(?)

          1. 2

            Do it anyway, always good to get different people’s perspectives.

        2. 1

          I think TGoPL will still be highly recommendable, even without a second edition. Almost all of it is related to the programming language (and braries), not how to build and manage dependencies. There’s one chapter on Go tooling, which will presumably require an update, and a couple of other mentions of go get and GOPATH, but I think overall it’s pretty “safe”. Don’t get me wrong; an update would be nice, but also wouldn’t require a rewrite by any means.

          1. 2

            A rewrite wouldn’t be needed as the language and stdlib mostly stayed the same, just a update which updates the tooling, and perhaps a few other things like context or the (upcoming) io/fs packages, but those things aren’t that hard to learn later on and don’t have too much potential for confusion (certainly not when starting out).

            I think the barrier to entry for these kind of things shouldn’t be underestimated; people read the gopl book, but they also read 3 blog posts, read something on HN, and they don’t know what is what. They try things, get errors they don’t understand and can’t solve, get confused/frustrated, and go do something else. At least, that’s what I usually do unless I really need to use something, but perhaps I just have a low tolerance for this kind of stuff.

        3. 7

          I have mixed feelings about this. On one hand, it does mean there will be just one correct way to handle Go dependencies. However, I’ve stubbed my toes on the modules system more than once, and many friends and colleagues have found it (the Go toolchain) a difficult system to learn and use in practice compared to C, Python, Java, and other languages.

          I think the biggest point of friction, at least for me, is that modules make it very difficult to develop multiple inter-related packages in tandem. For example, say I need to work on a patch for a library to fix a bug in some code I’m writing, and I also need to modify that code to test/evaluate the patch. With GOPATH, I can simply make the needed changes in GOPATH/src/github.com/foo/bar and go run/go build will automatically pick it up. Perhaps I misunderstand this announcement, but it sounds like this workflow will break.

          Go certainly tries to solve many problems with it’s packaging system which other languages have not even attempted to solve. However when I evaluate my own use of Go, and friends and colleagues at various stages of learning and using Go, I cannot help but feel that it is a great language hampered by a difficult toolchain. In my perception, there is an impedance mismatch between the much-touted simplicity of Go (I will vouch for this being true), and the comparative complexity of the modules system.

          1. 7

            I do exactly this all the time with modules; I just add

            replace zgo.at/zhttp => ../zhttp

            in my go.mod and it loads the local version. I even have a little Vim command for it:

            command! -nargs=1 Replace call append(4, printf('replace zgo.at/%s => ../%s', <f-args>, <f-args>))

            IMO it works better than GOPATH, because you don’t have a sprawling GOPATH where you may or may not have modified anything locally. It’s much clearer.

            1. 3

              Ok awesome! I never knew that. This will make my workflow much easier! I assumed it was like module imports and everything had to be absolute.

            2. 4

              I think you’ll still be able to do this with the replace directive.

              1. 1

                I was under the impression that replace could only work with remote paths, not local ones, unless this is changing.

                1. 6

                  Relative, local paths definitely work!

                  If the path on the right side of the arrow is an absolute or relative path (beginning with ./ or ../), it is interpreted as the local file path to the replacement module root directory, which must contain a go.mod file. The replacement version must be omitted in this case.


            3. 5

              I wish they had a very simple, clear explanation of how modules work. It’s not like we create modules every day, so it’s easy to forget about the quirks. I see even very popular modules doing things wrong in various ways (like including hundreds of unrelated packages in one module, not versioning, etc) so it’s not just me.

              1. 2

                Also recently seen a project where an author writing quite good Go though they must insert a go.mod file in every subdirectory of the project’s repo (o_O)

                1. 1

                  Oh no!

              2. 2

                This sounds resonable but it is surprising to me that they do this kind of changes in a minor release.

                1. 4

                  It is surprising, but toolchain is explicitly excluded from Go compatibility promise. See https://golang.org/doc/go1compat.

                  1. 5

                    The culture around Go’s tooling confuses me. On the one hand, the project obviously realizes that tooling is important for the language. On the other hand, any complaint about the conventions the tooling forces on you, or any complaint about the tooling itself, is met with a “it’s not part of the language, it’s just tooling, you don’t need to use it”. And evidently, the project doesn’t see tooling as something which people should in any way rely on, considering it changes in major backwards incompatible ways between minor releases.

                    I don’t get it.

                    1. 1

                      You could just use GCC for compiling Go:

                      gccgo -O2 main.go -o main

                      It makes sense that the language and tooling are separate, to avoid “the one true compiler” issue.

                2. 1

                  I recently started writing code in Go and I don’t understand what is changing.

                  I have packaged a Go application where I needed to extract sources in a specific directory in $GOPATH/src and it has a big Makefile that takes cares of downloading dependencies and building the application, so everything else was hidden for me.

                  Now, when I write an application, I don’t have my code in $GOPATH, and the directory structure there just seems to be a big dependency cache, which is versioned (much better than with Python where you have to use virtualenvs to avoid conflicts, or with native dependencies in e.g. C where it’s even harder to work with).

                  So what is changing for me, of for others? What was the advantage of having the code sitting in $GOPATH? Are you using separate $GOPATH directories for each application you develop on?

                  I have to use a go.mod file for managing dependencies, and it’s nice to have packaging managed directly by the language distribution, but the thing that troubles me is how a package is named after where their sources are located, which may not be right for an application having different source channels (e.g. private/public mirrors). I see two tricky solutions to this problem: patching go.mod files with replace directives, or maintain a directory structure with relative paths in replace directives (but you don’t always work on every dependency in a project). Then I understand why one would have their code sitting in $GOPATH/src.