Go Project Module Mechanism

Mastering any real project necessarily presupposes familiarity with the programming language’s module system.Go’s module system has some unique features, which are fully documented here.

GOPATH 和 Go Module

When installing Go on windows, one of the steps is to set the GOPATH environment variable, the value of which is the workspace path and can be set to the following by defaultC:\Users\<用户名>\goIn earlier versions, Go projects could only be placed in the GOPATH directory. In earlier versions, Go projects could only be placed in the GOPATH directory. Starting with version 1.13, Go Mudules is the default way to manage dependencies; Modules dictate the naming and dependencies of internal modules, project versioning, and external dependencies. If the project uses Go Modules, GOPATH is mainly used for storing downloaded dependency packages (caches) and so on.

Steps for using Go Modules

1. Initialize Go Modules

Run the following command in the root directory of the project:

go mod init <module-name>
  • <module-name>This is usually the module path of the project (e.g. the Git repository address), for example:
go mod init github.com/username/projectname
  • If it’s just a local project, feel free to specify a name like:
go mod init myproject

When the run completes, it generates ago.modfile, which reads as follows:

module myproject

go 1.20 // 你的 Go 版本

2. Developing your project

You are free to organize the code in the current directory, for example:

myproject/
├── go.mod
├── main.go
└── pkg/
└── mylib/
└── mylib.go

main.goThe package can be imported normally in the

package main

import "myproject/pkg/mylib" // 路径以项目名开头

func main() {
mylib.Hello()
}

3. Adding dependencies

If the project needs to introduce an external dependency library, use it directly in the code using theimport, then run the following command to install the dependencies:

go mod tidy

This will updatego.modand generates ago.sumfile, which is used to record all the project’s dependencies and their versions.

4. Compile and run the project

When you run the project, Go handles dependencies automatically:

go run main.go

Or generate a binary file:

go build

5. Separation of projects and dependencies

Project source code and dependencies are stored separately:

  • The project source code is saved in a directory you define (not subject to theGOPATH(Restrictions).

  • The dependency library cache is stored in theGOPATH/pkg/modCatalog.

The init function and import

This section is quoted from:

There are two reserved functions in golang: the init function (which can be applied to all packages) and the main function (which can only be applied to package main). These two functions cannot have any parameters or return values when they are defined.

Although it is possible to write as many init functions as you want in a package, it is highly recommended that you write only one init function per file in a package, both for readability and for future maintainability.

The go program calls init() and main() automatically, so you don’t need to call them anywhere. The init function is optional in every package, but the package main must include a main function.

Program initialization and execution starts with the main package. If the main package also imports other packages, they are imported in turn at compile time. Sometimes a package will be imported by more than one package at the same time, so it will only be imported once (e.g., the fmt package may be used by many packages, but it will only be imported once because there is no need to import it more than once).

When a package is imported, if the package also imports other packages, the other packages are imported first, then the package-level constants and variables in those packages are initialized, then the init function is executed (if it exists), and so on. When all the imported packages have been loaded, the package-level constants and variables in the main package are initialized, then the init function in the main package is executed (if it exists), and finally the main function is executed. The following diagram explains the whole process in detail:

init函数的作用链

Anonymous and alias imports

In Go, we can use_as an anonymous import, which avoids importing packages that are not needed. Example:

import (
"fmt"
_ "moduleTest/lib1"
)

In this way, we have only imported thefmtpackageslib1The code in the package will not be executed. But the init function in lib1 will still be executed.

If we want to import a package but want to give it an alias, we can add the alias in the same place. For example:

import (
"fmt"
we2 "moduleTest/lib2"
)