== The proper setup of a Go module, as I understand it I have been a little bit confused about some aspects of Go modules in practice for a while, and to get things more nailed down in my head, I'm writing some entries (writing entries here can be a form of [[talking to the duck ../tech/WhyTalkToTheDuck]]). This is the first one, because before I understand the unusual corner cases I need to cover the normal and proper cases. Suppose that you have a Go module _example.org/cks/mymod_, or a pre-modular Go package that would be a module if you modularized it, and this module is in a VCS repository of its own (which is the common case). As far as I know, there are two proper modern cases, one acceptable modern corner case, and one proper legacy case for your module or package. (Go expects to find the repository for your module starting at the URL using [[a documented approach that allows you to redirect to another location https://go.dev/ref/mod#vcs-find]].) First, your module can have either no version tags or version tags that say it has major version 0 or 1. In both cases, the module's import path is '_example.org/cks/mymod_' and your _go.mod_ should have that as the module's name in the '_module_' line. Second, your module can have a tag with a major version above 1, such as '2.1.0', but you have a normal source code layout with your code directly in _example.org/cks/mymod_. This makes the module's import path be '_example.org/cks/mymod/v2_' and your _go.mod_ should have this as the module name in the '_module_' line. This is the normal way to have a proper Go module that's above major version 1. Third, as what I think of as a corner case your module can have a tag with a major version above 1 but put the code for that version in an appropriately named subdirectory, such as _example.org/cks/mymod/v2_ or [[ github.com/pborman/getopt/v2_ https://github.com/pborman/getopt/tree/master/v2]]. This is still the module's import path, but now your _go.mod_ for that major version goes in [[_.../v2/go.mod_ https://github.com/pborman/getopt/blob/master/v2/go.mod]] and declares the module name as the v2 name. To avoid really confusing people, I think that the code outside of the subdirectory should be the v1 (or v0) code and thus have a _go.mod_ file that just calls it '_example.org/cks/mymod_'. (As far as I can tell from the documentation, Go doesn't accept version subdirectories for v0 and v1 major versions.) Technically I think you can have the _example.org/cks/mymod/v2_ subdirectory be major version 2 and the _example.org/cks/mymod_ root directory be, say, major version 3 and have it all work out with appropriate _go.mod_ contents in the root directory and in the _v2/_ subdirectory. However, this is likely to be rather confusing to people, and it's possible that the Go tools don't like this setup. If you started out with a _v2/_ subdirectory but want to move away from version subdirectories for your next major version, I think that it would work to release a v3 major version with the _v2/_ subdirectory deleted from the tree (as of that version tag). I believe that the one proper legacy case is that your package has major version 0 or 1, but no _go.mod_ because you haven't modularized yet. In this case, the import path is '_example.org/cks/mymod_'. Go's module tooling handles the case of a non-modular package having a higher major version than v1, but that's for another entry. It's possible to have modules be in subdirectories of the VCS repository root. In this case [[VCS version tags get complicated, as covered in the official documentation https://go.dev/ref/mod#vcs-version]]. However I believe the rest of it stays the same. Ultimately all of this (and much more) is documented in [[the "Version control systems" section of the official documentation https://go.dev/ref/mod#vcs]]. If you need to know the full details, expect to spend a while reading it carefully, and possibly taking notes as you go back and forth between sections to work out how various scenarios (probably) get handled.