1. Basic facts
- Go code is grouped into packages, and packages are grouped into modules.
- In Go, you import packages, not modules.
- A module usually contains a package with the same name as itself.
e.g
module1/
├── go.mod
├── module1.go
├── pkg1
│ └── pkg1.go
└── pkg2
└── pkg2.go
2 GOPROXY fetches imported modules for you
You may be curious about how https://pkg.go.dev/ knows so many go modules. The reason is simple, all imported modules by default are fetched by a server provided by the Go team and cached there.
$ go env GOPROXY
https://proxy.golang.org,direct
Let's say you have the below code:
import github.com/jung-kurt/gofpdf
When you run "go mod tidy" or "go get github.com/jung-kurt/gofpdf", the command actually tries to fetch this module from https://proxy.golang.org.
If it's not cached on the server yet, then proxy.golang.org will fetch it from github.com and return it to you. At the same time, a copy was cached there.
3 What if the module to import is private?
Open-sourcing is great but not all code should be public. It's inevitable to depend on some non-public modules in a real development environment.
The problem here is that the default GOPROXY will fail to fetch those private modules either because of a lack of credentials or an inaccessible network. Here are two examples.
- Your modules are on github.com but not public.
- Your modules are on your company's internal git server.
The solution is GOPRIVATE, a dedicated go environment variable for this problem. If a module path is included in GOPRIVATE, then it will be fetched directly without any proxy.
e.g
$ go env -w GOPRIVATE='*.your-company.com,github.com/your-company'
4 Special case: app and packages are in the same module
Most small projects usually don't have published modules at all. In this case, the simplest solution is to put app code and packages code into the same module.
project1/
├── app.go
├── go.mod
├── pkg1
│ └── pkg1.go
└── pkg2
└── pkg2.go
Just like above, both app.go and packages pkg1,pkg2 are managed by a single "go.mod".
When importing pkg1 in app.go, you still have to use the module path.
import example.com/project1/pkg1
But the go tools are clever enough to know that pkg1 is contained in the same module as app.go, and will NOT fetch it at all.
And since your packages' code will never be fetched by anyone remotely, the module path/name can be anything you want (here is "example.com/project1").
No comments:
Post a Comment