Golang环境变量
~/.bash_profileGOROOTGOROOT=/usr/local/goexport GOROOTexport $PATH:$GOROOT/bin;:cd ~mkdir gopath~/.bash_profileexport GOPATH=/Users/username/gopathGOPATHGOPATHbinpkgsrc$HOME/go$PATH${GOPATH//://bin:}/bin

Go Modules

go modules
GOPATH$GOPATH/src/modgo install$GOPATH/binGO111MODULE=offGO111MODULE=ongo.modGO111MODULE=auto$GOPATH/srcgo.modgolang.org/x/...go env -w GOPROXY=https://goproxy.cn,directexport GOPROXY=https://goproxy.cn

Go mod

$GOPATH/src$GOPATH/src
go modThe commands are:  download    download modules to local cache (下载依赖的module到本地cache))  edit        edit go.mod from tools or scripts (编辑go.mod文件)  graph       print module requirement graph (打印模块依赖图))  init        initialize new module in current directory (再当前文件夹下初始化一个新的module, 创建go.mod文件))  tidy        add missing and remove unused modules (增加丢失的module,去掉未用的module)  vendor      make vendored copy of dependencies (将依赖复制到vendor下)  verify      verify dependencies have expected content (校验依赖)  why         explain why packages or modules are needed (解释为什么需要依赖)GOPATHgo mod init packagenamego.modrequire github.com/smallnest/rpcx latestgo mod download$GOPATH$GOPATH/pkg/mod$GOPATH/github.com/smallnest/rpcxgo mod init github.com/smallnest/rpcxgo.modmodule github.com/smallnest/rpcxgo get ./...go.mod-tagsgo mod tidygo.modtagsgo.modlatestgo.sum

实战

示例一:创建一个新项目

GOPATH 目录之外go mod initgo.mod
➜  ~ mkdir hello
➜  ~ cd hello
➜  hello go mod init hello
go: creating new go.mod: module hello
➜  hello ls
go.mod
➜  hello cat go.mod
module hello

go 1.12

go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。

modulerequirereplaceexclude
modulerequirereplaceexclude
  1. 添加依赖

新建一个 server.go 文件,写入以下代码:

package main

import (
	"net/http"
	
	"github.com/labstack/echo"
)

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}
go run server.go
$ go run server.go
go: finding github.com/labstack/echo v3.3.10+incompatible
go: downloading github.com/labstack/echo v3.3.10+incompatible
go: extracting github.com/labstack/echo v3.3.10+incompatible
go: finding github.com/labstack/gommon/color latest
go: finding github.com/labstack/gommon/log latest
go: finding github.com/labstack/gommon v0.2.8
# 此处省略很多行
...

   ____    __
  / __/___/ /  ___
 / _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
                                    O\
⇨ http server started on [::]:1323

现在查看go.mod 内容:

$ cat go.mod

module hello

go 1.12

require (
	github.com/labstack/echo v3.3.10+incompatible // indirect
	github.com/labstack/gommon v0.2.8 // indirect
	github.com/mattn/go-colorable v0.1.1 // indirect
	github.com/mattn/go-isatty v0.0.7 // indirect
	github.com/valyala/fasttemplate v1.0.0 // indirect
	golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
)

go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit。go 会自动生成一个 go.sum 文件来记录 dependency tree:

$ cat go.sum
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
... 省略很多行
go run server.gogo list -m -u allgo get -u need-upgrade-packagego get -u

go get 升级

  • 运行 go get -u 将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
  • 运行 go get -u=patch 将会升级到最新的修订版本
  • 运行 go get package@version 将会升级到指定的版本号version
  • 运行go get如果有版本的更改,那么go.mod文件也会更改

示例二:改造现有项目(helloword)

项目目录为:

$ tree
.
├── api
│   └── apis.go
└── server.go

1 directory, 2 files

server.go 源码为:

package main

import (
    api "./api"  // 这里使用的是相对路径
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/", api.HelloWorld)
    e.Logger.Fatal(e.Start(":1323"))
}

api/apis.go 源码为:

package api

import (
    "net/http"

    "github.com/labstack/echo"
)

func HelloWorld(c echo.Context) error {
    return c.JSON(http.StatusOK, "hello world")
}

export GO111MODULE=on 先设置环境变量开启Module功能

go mod init ***
$ go mod init helloworld
go: creating new go.mod: module helloworld
go run server.go
go: finding github.com/labstack/gommon/color latest
go: finding github.com/labstack/gommon/log latest
go: finding golang.org/x/crypto/acme/autocert latest
go: finding golang.org/x/crypto/acme latest
go: finding golang.org/x/crypto latest
build command-line-arguments: cannot find module for path _/home/gs/helloworld/api
server.go
build command-line-arguments: cannot find module for path _/home/gs/helloworld/api
go.mod
$ cat go.mod
module helloworld

go 1.12

require (
        github.com/labstack/echo v3.3.10+incompatible // indirect
        github.com/labstack/gommon v0.2.8 // indirect
        github.com/mattn/go-colorable v0.1.1 // indirect
        github.com/mattn/go-isatty v0.0.7 // indirect
        github.com/valyala/fasttemplate v1.0.0 // indirect
        golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
)
那为什么会抛出这个错误呢?
变更引入方法
  1. 更新旧的package import 方式

所以server.go 需要改写成:

package main

import (
    api "helloworld/api"  // 这是更新后的引入方法
    "github.com/labstack/echo"
)

func main() {
    e := echo.New()
    e.GET("/", api.HelloWorld)
    e.Logger.Fatal(e.Start(":1323"))
}
一个小坑go build github.com/valyala/fasttemplate: module requires go 1.12go mod
  1. 到这里就和新创建一个项目没什么区别了

总结

Go Module是Go依赖管理的未来。从1.11之后开始支持该功能,随着Go依赖管理的功能增强,以后再也不用被现在的包管理犯难了。