源码

10分钟学会go module

前两天参加了 GopherChina 的大会收获颇多,go module算一个,下面把总结使用分享给大家,有问题的话希望指正。

基本使用

环境准备

  1. golang 1.11的朋友,开启 GO11MODULE=on ,并且确保实验目录不在 GOPATH 中

  2. golang 1.12的朋友,确保实验目录不在 GOPATH 中。

初始化go module环境

带git的项目

  1. 直接从github上面clone一个项目下来。

  2. 直接执行 go mod init 会自动生成带git地址的packagename

➜  gomodtest_base git:(master) ✗ go mod init
go: creating new go.mod: module github.com/e421083458/gomodtest_base

不带git的项目

  1. 直接执行

go mod init packagename

下载依赖包

只下载依赖包

go mod download
➜  new_module_test go mod download
go: finding github.com/e421083458/gomodtest_dep v0.0.0-20190501153957-6ff7f41fdb83
go: finding github.com/e421083458/gomodtest_base v1.0.1
go: finding github.com/e421083458/gomodtest_base/v2 v2.0.0
go: finding github.com/jianfengye/collection v0.0.0-20190426092112-28c4a03f0c86
go: finding github.com/pkg/errors v0.8.1

拉取必须模块,移除不用的模块

go mod tidy

注意点:

  1. 如果tag对应内容有更新,需要删除pkg中的缓存内容。这点比较恶心了。

cd $GOPATH/pkg/mod
rm -rf *
  1. go get、 go run、go build 也会自动下载依赖

添加新依赖包

方法一:
直接修改 go.mod 文件,然后执行 go mod download
方法二:
使用 go get [email protected],会自动更新 go.mod 文件的
方法三:
go run、go build 也会自动下载依赖

将依赖包下载到vendor目录

go mod vendor

注意: 这里只会下载对应版本的包文件,不会把所有版本下载。跟之前1.11使用方式一致。

亮点功能一:使用replace本地包替换

有时候国外软件可能被墙,这个功能就能派上用场了。
main.go

main.go

package main
import "my/example/pkg"
func main() {
   pkg.Hello()
}

go.mod

module my-mod

require my/example/pkg v0.0.0
replace my/example/pkg => ./pkg

注意点: 顶层依赖可替换但间接依赖不可替换

亮点功能二:语意化版本 semver—Semantic Versioning

semver是官方为了类库升级引入的新规范,即:
“If an old package and a new package have the same import path, the new package must be backwards compatible with the old package.” - go modules wiki "
如果旧软件包和新软件包具有相同的导入路径,则新软件包必须向后兼容旧软件包。"

main.go

package main
import (
   "fmt"
   v1 "github.com/e421083458/gomodtest_base"
   v2 "github.com/e421083458/gomodtest_base/v2"
)
func main(){
   v2.NewIntCollection("hello","sex")
   v1.NewIntCollection("hello")
   fmt.Println("hello");
}

go.mod

module new_module_test

require (
   github.com/e421083458/gomodtest_base v1.0.1
   github.com/e421083458/gomodtest_base/v2 v2.0.0
)

亮点功能三:依赖包冲突问题

情况1:直接 引用的包 和 间接引用的包是同一个包,但版本不同时?

依赖关系:
gomodtest_test|--> gomodtest_dep         |--> [email protected]
             |--> [email protected]    

go mod tidy 时,gomodtest_test会自动更新到与依赖包关联的第三方包相同版本号,并写入到go.mod,从而解决了版本冲突问题。

情况2: 间接引用的两个包是同一个包,但版本不同时?

go mod download
➜  new_module_test go mod download
go: finding github.com/e421083458/gomodtest_dep v0.0.0-20190501153957-6ff7f41fdb83
go: finding github.com/e421083458/gomodtest_base v1.0.1
go: finding github.com/e421083458/gomodtest_base/v2 v2.0.0
go: finding github.com/jianfengye/collection v0.0.0-20190426092112-28c4a03f0c86
go: finding github.com/pkg/errors v0.8.1

0

go mod tidy 时,默认使用第一个包引用版本号,[email protected],并写入到go.mod,这个时候就要注意两个版本是否功能完全兼容的问题了。

亮点功能四:自动查找包依赖

go mod 遵循了之前go get 自动下载依赖特性。所有的依赖包会自动全部下载。
未启用 go mod 功能的包会自动下载最高 tag 版本或最高 master commit版本
我之前也以为go mod只会自动查询使用了go mod的功能的包。

go mod download
➜  new_module_test go mod download
go: finding github.com/e421083458/gomodtest_dep v0.0.0-20190501153957-6ff7f41fdb83
go: finding github.com/e421083458/gomodtest_base v1.0.1
go: finding github.com/e421083458/gomodtest_base/v2 v2.0.0
go: finding github.com/jianfengye/collection v0.0.0-20190426092112-28c4a03f0c86
go: finding github.com/pkg/errors v0.8.1

1

总结:

  1. 大部分场景下 go mod init 和 go mod tidy 两个命令就够用了

  2. 查看$GOPATH/pkg/mod里面的文件就知道了,mod做了一件类似maven的事把所有包都打上了版本号。
    可以说这是 golang 迈向高大上语言的标志。
    从此我们不再为多版本使用的困扰,也不再为IDE打开一个新项目后等待n分钟的生成缓存犯愁。推荐大家丢掉vendor使用统一管理。

  3. semver 将版本信息绑定进包名对于习惯了传统包管理器方案的用户来说显得有些怪异,可能需要花上一些额外时间适应。

文档引用:
https://www.cnblogs.com/apocelipes/archive/2019/01/20/10295096.html
https://github.com/golang/go/wiki/Modules#semantic-import-versioning
https://www.cnblogs.com/apocelipes/p/9534885.html
https://www.cnblogs.com/apocelipes/p/9537659.html

(0)

本文由 投稿者 创作,文章地址:https://blog.isoyu.com/archives/10fenzhongxuehuigo-module.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:7 月 24, 2019 at 04:50 下午

热评文章

发表回复

[必填]

我是人?

提交后请等待三秒以免造成未提交成功和重复