GolangGolang

Golang Module学习使用

2019-01-09  本文已影响6人  ChainZhang

本文为转载,原文:Golang Module学习使用

Golang

介绍

美国当地时间2018年8月24日,Go 开发团队宣布推出 Go 1.11 正式版。

此版本增加了对被称作“模块(Go Modules)”的初步支持,这是 GOPATH 的替代方案,集成了对版本控制和软件包分发的支持。

自从Go 1.11 推出之后,一直也没有时间去学习新版本的特性,这次就来研究一下Go Modules的使用吧

1. go mod 命令

安装go 1.11版本后,可以通过以下命令大致看下go mod有哪些命令

go help mod
image.png

图中可以看到,go mod的命令语法为

go mod <command> [arguments]
  1. download: download modules to local cache (下载依赖的module到本地cache)
  2. edit: edit go.mod from tools or scripts (编辑go.mod文件)
  3. graph: print module requirement graph (打印模块依赖图)
  4. init: initialize new module in current directory (再当前文件夹下初始化一个新的module, 创建go.mod文件)
  5. tidy: add missing and remove unused modules (增加丢失的module,去掉未用的module)
  6. vendor: make vendored copy of dependencies (将依赖复制到vendor下)
  7. verify: verify dependencies have expected content (校验依赖)
  8. why: explain why packages or modules are needed (解释为什么需要依赖)

2. go mod的使用

接下来将通过一个简单的项目介绍go mod的使用

2.1. 新建项目

首先创建一个空文件夹,用作项目目录

mkdir modtest

然后通过init命令初始化mod

cd modtest
go mod init modtest

上述命令会在modtest目录下生成go.mod文件。

结果如下图所示


image.png

接下来,我们写一段简单的代码验证一下,在该目录创建main.go文件,写入以下代码:

package main

import (
    "fmt"
)

func main() {
    fmt.Println("hello word")
}

执行以下命令查看结果:

go run main.go
image.png

2.2. 添加github包

上一步成功创建了项目,接下来,我们要添加一个github的包,这里就简单的添加一个测试的包github.com/Chain-Zhang/modlib,这个是我自己做的一个及其简单的包,其中就只有一个方法,代码如下:

package modlib

func Message() string {
    return "this message from modlib"
}

这里打了个tag:v0.0.1

执行以下命令添加包到项目:

go get -m github.com/Chain-Zhang/modlib@v0.0.1

执行之后可以看下效果:


image.png

从图中可以看到,在go.mod文件中增加了一条内容:

module modtest

require github.com/Chain-Zhang/modlib v0.0.1 // indirect

另外又多出一个文件go.sum

github.com/Chain-Zhang/modlib v0.0.1/go.mod h1:vQ6MFJ522Kt0KC6N5sati+nKWd685pu216mW0cW6EMw=

go.mod 则是描述直接依赖包

go.sum 则是描述依赖树锁定

之后我们在项目中调用一下我们modlib的方法试一下,代码如下:

package main

import (
    "fmt"
    "github.com/Chain-Zhang/modlib"
)
  
func main() {
    msg := modlib.Message()
    fmt.Println(msg)
}

执行以下命令,看下效果:

go run main.go
// 输出:this message from modlib

2.2. 尝试下go mod命令

这个时候,我们可以尝试下gomod的几个命令

image.png

执行最后一个go mod vendor的时候,你会发现,在项目目录里面增加了个目录,vendor,而且,将所依赖的包也放进去了


image.png

2.3. go mod 翻墙

接下来,我们将modlib加入一段代码,该代码需引用golang.org/x/text:

package modlib

import(
    "golang.org/x/text/language"
    "golang.org/x/text/message"
    "golang.org/x/text/number"
)

func Message() string {
    return "this message from modlib"
}

func MaxIntegerDigits(){
    const year = 1999
    p := message.NewPrinter(language.English)
    p.Println("Year:", number.Decimal(year, number.MaxIntegerDigits(2)))
}

并将打上v0.0.2的tag

然后在项目中调用MaxIntegerDigits方法:

package main

import (
    "fmt"
    "github.com/Chain-Zhang/modlib"
)

  
func main() {
    msg := modlib.Message()
    fmt.Println(msg)
    modlib.MaxIntegerDigits()
}

在执行以下命令更新包到v0.0.2:

go get github.com/Chain-Zhang/modlib@v0.0.2
// 错误:
// go build golang.org/x/text/message: no Go files in
// go build golang.org/x/text/number: no Go files in
// go build golang.org/x/text/language: no Go files in

这是因为获取golang.org/x/...时需要翻墙,而我这里没有翻墙,不过没关系,设置下代理即可:

// bash mac
export GOPROXY=https://goproxy.io

// powershell windows
$env:GOPROXY = "https://goproxy.io"

然后再执行命令:

go get github.com/Chain-Zhang/modlib@v0.0.2
// go: finding golang.org/x/text/message latest
// go: finding golang.org/x/text/language latest
// go: finding golang.org/x/text/number latest

成功之后go.mod及go.sum的变化:

// go.mod
module modtest

require (
    github.com/Chain-Zhang/modlib v0.0.2
    golang.org/x/text v0.3.0 // indirect
)

// go.sum
github.com/Chain-Zhang/modlib v0.0.2 h1:Rj839yAnYX7yER2s28+92fDTkOTRqjr2AJIZ4vqTvRk=
github.com/Chain-Zhang/modlib v0.0.2/go.mod h1:vQ6MFJ522Kt0KC6N5sati+nKWd685pu216mW0cW6EMw=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

2.4. 版本回到v0.0.1

这个时候我们把版本再回到v0.0.1

go get github.com/Chain-Zhang/modlib@v0.0.1

这个时候因为我们调用了v0.0.2的modlib.MaxIntegerDigits方法,所以会报错,只要删掉就可以了。

但是在我们的go.mod中却有个多余的引用,即golang.org/x/text,因为v0.0.1中没有用到该包。

此时我们就可以执行go mod tidy来清除不必要的引用,和添加丢失的引用。执行之后,go.mod文件中对于golang.org/x/text的引用就不见了。

2.5. 其他

2.5.1. go get 命令

获取依赖的特定版本,用来升级和降级依赖。可以自动修改 go.mod文件,而且依赖的依赖版本号也可能会变。

与以前不同的是,新版 go get可以在末尾加 @符号,用来指定版本。
它要求仓库必须用 v1.2.0格式打 tag,像 v1.2
少个零都不行的,必须是语义化的、带 v前缀的版本号。

eg:

go get github.com/gorilla/mux    # 匹配最新的一个 tag
go get github.com/gorilla/mux@latest    # 和上面一样
go get github.com/gorilla/mux@v1.6.2    # 匹配 v1.6.2
go get github.com/gorilla/mux@e3702bed2 # 匹配 v1.6.2
go get github.com/gorilla/mux@c856192   # 匹配 c85619274f5d
go get github.com/gorilla/mux@master    # 匹配 master 分支

2.5.2. go build 命令

  1. go build -mod=readonly 防止隐式修改 go.mod,如果遇到有隐式修改的情况会报错,可以用来测试 go.mod 中的依赖是否整洁,但如果明确调用了 go mod、go get 命令则依然会导致 go.mod 文件被修改。

  2. go build -mod=vendor 在开启模块支持的情况下,用这个可以退回到使用 vendor 的时代。

本文为原创,转载请注明出处: Golang Module学习使用

上一篇下一篇

猜你喜欢

热点阅读