I have a project that looks similar to this tree:
. proj
├── README.md
├── go.mod
├── go.sum
├── subpackage
│ ├── one.go
│ ├── two.go
│ ├── three.go
│ └── four.go
├── main.go
In main.go I am importing a struct and some methods via github.com/username/proj/subpackage.
I am not using subpackage in any other projects (only this project).
Should I have a separate go.mod file within subpackage/ in addition to the go.mod file in project root? And consequently should the subpackage be listed in project-root's go.sum file?
If not, would I need it in the case where the subpackage directory/package is being used in a completely separate project?
A separate go.mod for subpackages is unnecessary. With such a go.mod file it is possible to separately tag the subpackage with a different version than the root package. This usecase is only needed in very specialized instances, where you want to have different versions for packages inside the same repository, so do not do that.
You do not have to modify go.sum manually at all. It should only be modified by the go-tooling (go get, go build), automatically.
Even if the subpackage is used inside another project by importing it, you do not have to give the subpackage a different version. When this subpackage is imported the go-tool will search for the root of the git repository, download the repository automatically with go get and make it available for importing.
Related
I am trying to learn Go modules dependency manager but getting an error while importing auto-generated proto definitions. Have been struggling with this for 2 days. Any help will be greatly appreciated.
Directory structure:
➜ ~/go-service-skeleton> tree .
.
├── protobuf
│ └── test_service
│ ├── test_service_config.pb.go
│ └── test_service_config.proto
├── src
│ └── test_service
│ ├── go.mod
│ ├── main.go
│ └── server
│ └── server.go
Error (last error is particularly concerning):
➜ ~/go-service-skeleton/src/test_service go build
bootstrap.go:11:2: no required module provides package github.com/Sirupsen/logrus; to add it:
go get github.com/Sirupsen/logrus
bootstrap.go:12:2: no required module provides package github.com/sirupsen/logrus; to add it:
go get github.com/sirupsen/logrus
bootstrap.go:13:2: no required module provides package gopkg.in/yaml.v2; to add it:
go get gopkg.in/yaml.v2
server/server.go:8:2: package protobuf/test_service is not in GOROOT
~/go-service-skeleton/src/test_service echo $GOPATH
/Users/****/go-service-skeleton:/Users/****/go-service-skeleton/protobuf
~/go-service-skeleton/src/test_service echo $GOROOT
Within your test_service module, the only dependencies visible to the go command are the ones declared in its go.mod file.
The simplest fix is to put all of the source code you need inside the main module. Note that per https://blog.golang.org/generate, “if the containing package is intended for import by go get, once the file is generated (and tested!) it must be checked into the source code repository to be available to clients.”
Suppose I have a monorepo and there are several individual golang services:
root
└── services
├── svc1
│ ├── go.mod
│ ├── go.sum
│ └── main.go
└── svc2
├── go.mod
├── go.sum
└── main.go
Whereas svc2 will depend on svc1 in the future. Also, it is a requirement that svc1 and svc2 can be released individually.
Is there a way I can publish the module indivdually? The go mod documentation only assume that there is only repo so it doesn't provide such flexibility.
To tag a release version for a module within a subdirectory of a repository, add the subdirectory as a prefix of the tag, like svc1/v0.1.0.
Per https://golang.org/ref/mod#vcs-version:
If a module is defined in a subdirectory within the repository …, then each tag name must be prefixed with the module subdirectory, followed by a slash. For example, the module golang.org/x/tools/gopls is defined in the gopls subdirectory of the repository with root path golang.org/x/tools. The version v0.4.0 of that module must have the tag named gopls/v0.4.0 in that repository.
So I created a simple test project to demonstrate the issue I'm having in a much larger code base here https://github.com/cleblanc189/test.go
.
├── go.mod
├── main.exe
├── main.go
├── server
│ ├── v1beta1
│ │ ├── foo.go
│ │ └── go.mod
│ └── v1ga
│ ├── foo.go
│ └── go.mod
└── service
├── v1beta1
│ ├── foo.go
│ └── go.mod
└── v1ga
├── foo.go
└── go.mod
I'd like to be able to reference service/v1beta1 from server/v1beta1 but I'm getting this error
go: test.go/src/server/v1beta1#v0.0.0 requires
test.go/src/service/v1beta1#v0.0.0: unrecognized import path "test.go/src/service/v1beta1" (https fetch: Get https://test.go/src/ser
vice/v1beta1?go-get=1: dial tcp: lookup test.go: no such host)
In foo.go from server/v1beta1 I import like this
svc "test.go/src/service/v1beta1"
and have a go.mod file like below;
require test.go/src/service/v1beta1 v0.0.0
replace test.go/src/service/v1beta1 => ../../service/v1beta1
When I try to cd src && go mod tidy I get that error above. Also if anyone knows should I even have a go.mod above the src directory?
Appreciate any help anyone can offer. This is maddening.
Your go.mod has to declare the module path/name, typically like this:
module test.go
Then all the imports in your code will be taken relative to that. When you import something relative to your declared module name, the go tool will automatically pick up the code from the right place locally.
Not sure where your src comes into play though... is everything in folder src? See this post and accompanying code for a complete example you could start from.
I have the following project structure
.
├── README.md
├── protos
│ ├── my-proto-output.pb.go
│ └── my-proto.proto
└── grpc-backend
├── client
│ └── client.go
├── go.mod
├── go.sum
├── main.go
└── a-submodule
Inside grpc-backend/main.go I have:
package main
import (
pb "github.com/my-user/my-repo/protos"
"google.golang.org/api/option"
"google.golang.org/grpc"
)
Inside go.mod I have
go 1.13
require (
google.golang.org/api v0.14.0
google.golang.org/grpc v1.21.1
)
module github.com/my-user/my-repo/grpc-backend
However, when I run cd grpc-backend && go build I get
go: finding github.com/my-user/my-repo latest
go: finding github.com/my-user/my-repo/protos latest
go: downloading github.com/my-user/my-repo v0.0.0-20200103231607-5a754c449f99
verifying github.com/my-user/my-repo#v0.0.0-20200103231607-5a754c449f99: github.com/my-user/my-repo#v0.0.0-20200103231607-5a754c449f99: reading https://sum.golang.org/lookup/github.com/my-user/my-repo#v0.0.0-20200103231607-5a754c449f99: 410 Gone
I don't have any tags like that, I'm in a private repo only commiting to master at the moment. Furthermore, proto's are in this same git repo under the package myrepo.
Questions:
Did I organize this incorrectly?
Where did that version come from? It's not in go.sum
Your module does not include the protos package, and thus, the generated grpc source. Move your go.mod one level up, and change the module name to github.com/my-user/my-repo so the module includes all packages.
I have some problems with how Go importing and modules works.
I have a project with this structure:
My-Project
|- Program 1
|- main.go
|- go.mod
|- Program 2
|- main.go
|- go.mod
|- Support
|- go_file.go
The two programs have different module "definition". I need to include the "Support" folder, which is shared between the two programs. I tried
import "My-Project/Support"
inside Program1's main.go, but this is not working, because Support can’t be resolved. How can I do it?
As given, your Support/go_file.go is not in any module so it's not importable using Go modules.
Either use a single module for all three packages or use three separate modules (i.e. put Support in it's own module). You could also use sub-modules.
Single module:
For a single module you'd do something like:
└── My-Project
├── go.mod
├── Program\ 1
│ └── main.go
├── Program\ 2
│ └── main.go
└── Support
└── go_file.go
And the project level go.mod would be something like:
module github.com/My-Name/My-Project
(substitute with appropriate module name) and then both main packages would import the support package with:
import "github.com/My-Name/My-Project/Support"
Note Go packages normally do not start with capitals like this.
More idiomatic for such a setup with a single repository which mixes packages and commands is a layout that puts commands into a cmd subdirectory (e.g. see the golang.org/x/tools layout). This would look something like this:
└── My-Project
├── cmd
│ ├── program1
│ │ └── main.go
│ └── program2
│ └── main.go
├── go.mod
├── internal
│ └── support
│ └── support.go
└── other-package
└── some-other-package.go
Here the support package is in an internal sub-directory which makes it non-importable from outside My-Project where-as the other-package is importable by anyone.
Again, go.mod would define the module name which sets the prefix to be used for all import statements.
Separate modules:
To use separate modules you'd do something like:
└── My-Project
├── Program\ 1
│ ├── go.mod
│ └── main.go
├── Program\ 2
│ ├── go.mod
│ └── main.go
└── Support
├── go_file.go
└── go.mod
Here My-Project/Program 1/go.mod would be something like:
module "github.com/My-Name/My-Project/Program 1"
require (
github.com/My-Name/My-Project/Support
)
The imports would be the same as for the single module example.
Similarly for Program 2. For Support/go.mod it'd look something like:
module github.com/My-Name/My-Project/Support
For local development you'll probably also want/need a replace directive in each program's go.mod to use your local working copy of the support module (go mod edit -replace github.com/My-Name/My-Project/Support=../Support should add this).