1. 创建一个mudule并且发布
1.1 $GOPATH/src目录结构
1.2 环境变量
需要增加环境变量:GO111MODULE=on
;
这个变量有三个可选值:
- on(Go启用在任何地方启用这个特性),
- off(禁止这个特性),
- auto(default,在GOPATH禁用在其他地方启用)
不然下一步console会输出
go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'
1.3 进入到hello目录
执行命令:go mod init github.com/Aruforce/hello
console输出:go: creating new go.mod: module github.com/Aruforce/hello
增加了一个文件 go.mod :
module github.com/Aruforce/hello
go 1.12 //go 的版本
1.4 增加代码
hello.go:
package hello
func Hello() string {
return "Hello, world.";
}
hello_test.go
package hello
import "testing"
func TestHello(t *testing.T) {
want := "Hello, world."
if got := Hello(); got != want {
t.Errorf("Hello() = %q, want %q", got, want)
}
}
1.5 发布
1.5.1 发布
git add * //添加文件
git commit -m 'first commit' //注释
git remote add origin https://github.com/Aruforce/hello.git //添加远程仓库
git push -u origin master //推送
1.5.2 打tag及推送
git tag v1.0.0 //注意 这个格式是Go的规定,格式为 v(major).(minor).(patch)
git push --tags //推送 tag
git checkout -b v1 //检出v1分支,防止有BUG然后修改
git push -u origin v1 //推送空内容到branch v1 也就是在远程新建一个分支
2. 在新工程中使用上面的module
2.1 目录结构
2.2 代码文件
mod.go:
package modtest
import (
"fmt"
"github.com/Aruforce/hello"
)
func Mod() string{
return hello.Hello();
}
mod_test.go:
package modtest
import "testing"
func TestMod(t *testing.T) {
want := "Hello, world."
if got := Mod(); got != want {
t.Errorf("Mod() = %q, want %q", got, want)
}
}
2.3 初始化工程
go mod init github.com/Aruforce/modtest
2.4 下载依赖代码
命令:
go get
//下载的代码等等会在$GOPATH/pkg/mod目录下
console:
go: finding github.com/Aruforce/hello v1.0.0
go: downloading github.com/Aruforce/hello v1.0.0
go: extracting github.com/Aruforce/hello v1.0.0
go.mod:
module github.com/Aruforce/modtest
go 1.12
require (
github.com/Aruforce/hello v1.0.0
// 因为代码里面没有指定版本等等相关信息而我们引用的代码又发布了v1.0.0,
//go get 会拉去v1.x.x tag list中最大版本号的代码;
//如果没有发布tag go 会造一个假的版本号v0.0.0-时间-commit code
//这个code为(第一次拉去代码时最后一次的master 的commit hashcode),
//然后拉取代码,除此之外,go 进行构建时不会主动更新这些代码,除非我们主动要求更新比如 go get -u
// 看到这个文件,其实直接手动修改版本号就可以了,不需要使用什么 go get -u patch什么...
)
go.sum:
github.com/Aruforce/hello v1.0.0 h1:CNC4ZenBDAah3mib7fwBztu9ZHVYkjNzMAKMhKlLreQ= //工程版本
github.com/Aruforce/hello v1.0.0/go.mod h1:SPJXz6EybRNTFDg7RAoekS+HdftZtWbdXaa8W+Mr8YM= //这个module 自己go.mod文件MD5值,作为安全性的校验
2.5 hello 版本更新了导致 modtest也要更新的情况
2.5.1 minor或者pacth更新
我们要做的只有一件事
go get -u
或者
go get -u =patch //这只会升级一个patch 如果有 v1.0.0 v1.0.1 v1.0.2 这个执行完后只会下载 v1.0.1的代码
或者
go get github.com/Aruforce/hello@v1.0.2 //这就是下载指定的版本代码
2.5.2 major更新
在Go看来Major的更新就是不同的依赖了,然而我觉得没有什么乱用,因为要对于一个代码要保持兼容,最为稳妥的办法在于不修改旧有的API,也就是对开闭原则:API只允许增加不允许修改;
2.5.2.1 需要同时使用一个代码库,版本冲突的情况
看如下代码
package modtest
import (
"fmt"
"github.com/Aruforce/hello" // v1版本
hv2 "github.com/Aruforce/hello/v2"
//v2对go来说相当于一个全新的依赖了,对于这种模式的路径golang赋予的别名还是hello就原版本有名字上的冲突,需要特别声明,也就是一种冲突解决方法
// 进行go get等等时,会下载 v2.x.x的代码
)
func Mod() string{
fmt.Println(hv2.Hello());
return hello.Hello();
}
2.5.2.2 直接大版本升级的情况
看如下代码:
package modtest
import (
"fmt"
"github.com/Aruforce/hello/v2"//v2对go来说相当于一个全新的依赖了,对于这种模式的路径golang赋予的别名还是hello,这就造成一个情况,原本自己的代码完全不需要修改
//go get 等等时,会下载v2.x.x最大版号的代码
)
func Mod() string{
return hello.Hello();
}
2.5.2.3 和我们没有关系的情况
看如下代码
package modtest
import (
"fmt"
"github.com/Aruforce/hello" // v1版本
//这种情况下,小版本patch更新,只要我们不手动 go get -u 本地代码就不会影响
//大版本更新,即使go get -u 也不会更新到大版本,除非显示生命
//其余就是使用你指定的新版本
)
func Mod() string{
return hello.Hello();
}
3. 去除掉多余的依赖
因为go 构建时不会主动去除多余的依赖,所以我们要手动去除,执行以下命令
go mod tidy
4. 没有发现go module 有本地仓库的概念
大概是不需要吧...文本文档才多大...而且人家也没有墙...
5. 希望 go module 可以稳下来作为一个固定的feature...vendor 貌似要被废弃了...
6. 我感觉比maven还是差一些;原因如下:
- maven是先制定了开发测试部署流程及依赖坐标化这两套标准,而maven和jar中央仓库只是标准的实践;go mod感觉就是个连实践都算不上的小shell脚本;
- go 内置约定太多,而且这些内置约定还不允许修改,还和编译器混合在一起
- 目前为止还没看到关于资源文件处理的插件(这个可能并不是很需要...不一定要按照环境来做配置文件)
- 文档太简陋了