GO111MODULE用来表明是否使用go module,GO111MODULE=off表明使用传统的GOPATH模式,GO111MODULE=on表明使用go module模式

使用gopath模式

使用gopath模式时,项目文件以及依赖包都需要在$GOPATH目录下,否则会出现问题:

假设如下两个文件在$GOPATH之外的路径,可以看出,main函数中需要引用local_dep目录下的文件,但是此时import中的路径却没法填写,如果使用绝对路径会报cannot import absolute path的错误,使用的命令为 GO111MODULE=off go run main.go

// 文件路径
.
├── local_dep
│   └── dep.go
└── main.go

// dep.go
package local_dep
import "fmt"
func Print() {
    fmt.Println("hello world")
}

// main.go
package main
import "???/local_dep"
func main() {
    local_dep.Print()
}

如果将其放在$GOPATH路径下,则将路径修改为相对于$GOPATH的路径即可,具体如下:

$GOPATH/src/test
├── local_dep
│   └── dep.go
└── main.go

// dep.go
package local_dep
import "fmt"
func Print() {
    fmt.Println("hello world")
}

// main.go
package main
import "test/local_dep"
func main() {
    local_dep.Print()
}

// GO111MODULE=off go run main.go

同样的,当在gopath模式下,对应的依赖包也会在$GOPATH/src下,使用 GO111MODULE=off go get xxx即可在$GOPATH/src下看到对应的依赖包,随之带来的问题就是相同依赖包的不同版本将难以维护。

使用go module

当使用go module后,项目就不需要写在$GOPATH路径下了,依赖包仍然会在$GOPATH下,不过是在./pkg/mod目录下,并且有版本号的标示,来区分同一依赖包的不同版本。项目结构如下:

// 文件路径
.
├── go.mod
├── local_dep
│   └── dep.go
└── main.go

// go.mod
module hello
go 1.13

// dep.go
package local_dep
import "fmt"
func Print() {
    fmt.Println("hello world")
}

// main.go
package main
import "hello/local_dep"
func main() {
    local_dep.Print()
}

// GO111MODULE=on go run main.go

main.go中只需要引入相对该module的路径即可引用到子目录中的函数,并且通过GO111MODULE=on go get -u或者go mod tidy的方式就可以在$GOPATH/pkg/mod下载到相应版本的依赖包

引用本地的依赖包

可能会存在本地调试的时候,想引用本地的依赖包(也就是这个包不在github上)的情况,分为下面四种情况讨论:

  1. 项目在$GOPATH下,GO111MODULE=off :import路径为依赖包相对于$GOPATH的路径即可跑通
  2. 项目在$GOPATH下,GO111MODULE=on:如果依赖包在同一go.mod下,可以直接引用;否则需要在go.mod中显示的将import的依赖包replace到依赖包的绝对路径下
  3. 项目不在$GOPATH下,GO111MODULE=off:没法跑
  4. 项目不在$GOPATH下,GO111MODULE=on:和第二种情况相同

情况2举例:

  1. 当引用的包在同一个go.mod下:与上面例子相同
  2. 当引用的包不在同一个go.mod下:
.
├── dep
│  ├── dep.go
│  └── go.mod
└── main_project
    ├── go.mod
    └── main.go


// dep/dep.go
package local_dep

import "fmt"

func Print() {
    fmt.Println("aa")
}

// dep/go.mod
module local_dep

go 1.13

// main_project/go.mod
module main_mod

go 1.13

replace local_dep v0.0.0 => $absolute_path/dep

require local_dep v0.0.0

// main_project/main.go
package main

import "local_dep"

func main() {
    local_dep.Print()
}

通过将本地依赖包replace到本地的绝对路径下,即可进行调用

参考资料

https://insujang.github.io/2020-04-04/go-modules/