I have a Go project with structure somewhat like this
github.com/my/coolproject
│
└───project
│ file1.go
│ file2.go
│ go.mod (github.com/my/coolproject/project)
│ ...
│
└───package1
│ file1.go
│ file2.go
│
...
│
packagex
│ file1.go (import github.com/my/coolproject/project/package1)
│ file2.go
I would like to create v2 of the project but not sure how to go about doing that.
I tried creating v2 directory at the root of the repo, copy content of the project folder into it and update the go.mod file to github.com/my/coolproject/project/v2
With this I also had to update the imports to v2 however the directory structure now didn't match precisely so I had to change imports from
import github.com/my/coolproject/project/something
to import github.com/my/coolproject/v2/something
removing the 'project' and adding 'v2'.
This causes bunch of cannot find module ... errors, when I remove the 'project' from the go.mod module path in v2 then it starts working.
However now there is a difference between the original project import path and the v2
github.com/my/coolproject/project
for the original vs v2 github.com/my/coolproject/v2
Is there a way how to keep the original with just v2 at the end? The problem is that then it doesn't really match the folder structure. I though about moving the v2 folder with new version into the project folder, but that sounds like a bad idea.
I though about moving the v2 folder with new version into the project folder, but that sounds like a bad idea.
2021: Yet, it seems to follow the official Go wiki on "Releasing Modules (v2 or Higher)"
Major subdirectory:
- Create a new v2 subdirectory (e.g., my/module/v2) and place a new
go.mod
file in that subdirectory.
The module path must end with/v2
.- Copy or move the code into the v2 subdirectory.
- Update import statements within the module to also use
/v2
(e.g.,import "github.com/my/module/v2/mypkg"
).- Tag the release with
v2.0.0
.
The other approach would be:
Major branch:
Update the
go.mod
file to include a/v2
at the end of the module path in the module directive (e.g.,module github.com/my/module/v2
).
- Update import statements within the module to also use
/v2
(e.g.,import "github.com/my/module/v2/mypkg"
).- Tag the release with
v2.0.0
.
No subfolder to create there.
And you can set your default branch to a v2
branch instead of main
, if you want people cloning your repository to get by default the latest version.
Q3, 2024: The major subdirectory approach is applied to Go itself, as detailed by Ian Lance Taylor in "spec: language change review meeting minutes":
For a few years now we've been running a proposal meeting known as the Go 2 proposal committee or the v2 committee. The original goal of the committee was to review proposed changes to the Go language and incompatible changes to the Go standard library. The minutes of the actions and decisions taken can be found in this issue.
Since the committee started Go has developed a standard way for handling incompatible Go library changes: a v2 release of the package.
The recent Go 1.22 release introduced the first incompatible change to the standard library, by adding
math/rand/v2
as a replacement formath/rand
.
(This is, of course, not really incompatible, as old programs continue to usemath/rand
and continue to work. Programs can update to the (slightly) incompatiblemath/rand/v2
at their leisure.)This means that there is no longer a compelling reason to separate out incompatible library changes into a separate process. They can go through the regular proposal process instead.
Therefore, we are renaming the v2 committee to the language review committee, and going forward it will only handle language changes. Historically when the v2 committee sees a language change that seems worthy of broader attention, the proposal has been handed off to the regular proposal committee for final review. That will continue: the role of the language review committee will be to do a first pass review of language change proposals, and pass the desirable ones on to the regular proposal committee.
You can see the v2
subdirectory in the src/math/rand
directory.
Learn more with "Evolving the Go Standard Library with math/rand/v2
, Principles for evolving the Go standard library":
One of the goals for this work was to establish principles and a pattern for how we approach all v2 packages in the standard library.
There will not be a glut of v2 packages in the next few Go releases. Instead, we will handle one package at a time, making sure we set a quality bar that will last for another decade.
Many packages will not need a v2 at all. But for those that do, our approach boils down to three principles:
First, a new, incompatible version of a package will use
that/package/v2
as its import path, following semantic import versioning just like a v2 module outside the standard library would. This allows uses of the original package and the v2 package to coexist in a single program, which is critical for a gradual conversion to the new API.Second, all changes must be rooted in respect for existing usage and users: we must not introduce needless churn, whether in the form of unnecessary changes to an existing package or an entirely new package that must be learned instead. In practice, that means we take the existing package as the starting point and only make changes that are well motivated and provide a value that justifies the cost to users of updating.
Third, the v2 package must not leave v1 users behind. Ideally, the v2 package should be able to do everything the v1 package could do, and when v2 is released, the v1 package should be rewritten to be a thin wrapper around v2. This would ensure that existing uses of v1 continue to benefit from bug fixes and performance optimizations in v2. Of course, given that v2 is introducing breaking changes, this is not always possible, but it is always something to consider carefully.