23

Go mod 开发中常用玩法 -- 开发必备

 3 years ago
source link: https://studygolang.com/articles/29277
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

go modules 是 golang 1.11 新加的特性。

那么问题来了,它解决了什么问题,其实核心的问题就是,他可以没有GoPath这个概念,所以很方便,但是当你不会使用的时候,你会觉得它很不好用。

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

简单使用

比如,现在有一个需求是,我们要创建一个新项目,项目名字为 go-kit-demo,此时我们需要go-kit的依赖,那么怎么办呢

第一步

% mkdir go-kit-demo

% cd go-kit-demo

% go mod init go-kit-demo // 初始化一个项目名为 go-kit-demo,这个路径其实是你相对于GOPATH的路径,以后你的包就是 import "go-kit-demo/util" 之类的

% ls
go.mod // 发现多了个文件

% cat go.mod
module go-kit-demo // 模块名字

go 1.13 // go版本

% go mod edit -require=github.com/go-kit/kit@latest //添加go-kit的依赖

% go mod download //下载依赖

% cat go.mod
module go-kit-demo

go 1.13

require github.com/go-kit/kit v0.10.0 // indirect

% ls
go.mod    go.sum//校验包
复制代码

第二步,其实就是需要代码,让编辑器可以找到,显然目前go官方不支持的,需要第三方。

​ 但是这里你无法直接使用go-kit,理由是,goland工具不支持,这种模块依赖,所以必须引入到vendor中,也就是。

这里推荐一个工具,他可以将依赖打包到vendor进去,相当nice

https://github.com/nomad-software/vend
复制代码

根据要求来就行了

go get github.com/nomad-software/vend
复制代码

就像下面这样子

~/go/code/mode-test % vend
vend: copying cloud.google.com/go (v0.34.0)
vend: copying github.com/BurntSushi/toml (v0.3.1)
vend: copying github.com/Knetic/govaluate (v3.0.1-0.20171022003610-9aa49832a739+incompatible)
vend: copying github.com/Shopify/sarama (v1.19.0)
vend: copying github.com/Shopify/toxiproxy (v2.1.4+incompatible)
vend: copying github.com/VividCortex/gohistogram (v1.0.0)
vend: copying github.com/afex/hystrix-go (v0.0.0-20180502004556-fa1af6a1f4f5)
vend: copying github.com/alecthomas/template (v0.0.0-20190718012654-fb15b899a751)
vend: copying github.com/alecthomas/units (v0.0.0-20190717042225-c3de453c63f4)
vend: copying github.com/apache/thrift (v0.13.0)
vend: copying github.com/armon/circbuf (v0.0.0-20150827004946-bbbad097214e)
复制代码

所以还是很方便的,可以将依赖全部copy到vendor下,就可以愉快的使用了。

其他命令

比如说国内源的问题,需要修改一下

export GOPROXY=https://goproxy.cn
复制代码

其次就是,比如低版本的go ,可能需要强制开启go mod

export GO111MODULE=on
复制代码

像其他命令我就不介绍了,比如还有常用的可能就是 go mod vendor ,将依赖copy到vendor目录下,但是有个问题就是,它只会copy代码依赖的东西,所以我们有些时候是不方便的,因此,需要使用到我上面推荐的工具。

比如说

go get github.com/go-kit/kit //此时会在go.mod文件中添加依赖,也就是说不需要手动的去执行 go mod edit -require=github.com/go-kit/kit@latest了
复制代码

还有其他命令

Go mod provides access to operations on modules.

Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.

Usage:

	go mod <command> [arguments]

The commands are:

	download    download modules to local cache//下载
	edit        edit go.mod from tools or scripts//编辑go.mod
	graph       print module requirement graph// 打印依赖
	init        initialize new module in current directory //初始化
	tidy        add missing and remove unused modules // 删除没用的依赖
	vendor      make vendored copy of dependencies // copy到vendor
	verify      verify dependencies have expected content // 校验
	why         explain why packages or modules are needed

Use "go help mod <command>" for more information about a command.
复制代码

go.mod 提供了 module , requirereplaceexclude 四个命令

module
require
replace
exclude

其实这些不需要care

本地仓库如何解决

需求,我们现在有另外一个项目,我们这个项目需要引入。

​ PS: 进入公司,一般你会将公司的代码,放在同一个目录下面,也就是上一级目录是一样的,所以我们也遵守这个规范,理由其实很简单,因为方便环境。

初始化 A\B项目,名字为 demo-1,demo-2

~/go/code/test % cd demo-1
~/go/code/test/demo-1 % ls
~/go/code/test/demo-1 % go mod init demo-1
go: creating new go.mod: module demo-1
复制代码

我们目前目录结构是这样的:

~/go/code/test % tree .
.
├── demo-1
│   └── go.mod
└── demo-2
    ├── api
    │   └── userservice.go
    └── go.mod

3 directories, 3 files
复制代码

我们现在demo-1这个项目,需要使用 user-service这个接口

package api

type UserService interface{
	GetUserInfo()*UserInfo
}

type UserInfo struct{
	Name string `json:"name"`
	Age  int  `json:"age"`
}
复制代码

此时只需要在 demo-1里面做一下替换就可以了,如下图所示

module demo-1

go 1.13

require demo_2 v0.0.0

replace demo_2 => ../demo-2
复制代码

然后我们demo-1就可以愉快的使用了

package main

import (
	"demo_2/api"
	"fmt"
)

func main() {
	info := api.UserInfo{
		Name: "tom",
		Age:  18,
	}
	fmt.Println(info)
}
复制代码

那么现实中,可能依赖包要更新,需要及时的拉去master,这个更新怎么办,很简单,只需要执行 go mod vendor 从新拉去一下

​ 注意的一点是 本地包,无法校验hash

为什么要必须使用vendor目录

  • 1、依赖可能是本地,可能是私有仓库,无法解决
  • 2、生产环境可能拉去慢
  • 3、没有通用的解决方案,等go以后发展吧

其中 go build -mod=vendor 的意思是强制开启vendor模式,依赖只会去vendor目录找,其他都不会care,也不会网络环境找。

私人仓库如何解决

全部公有仓库,没啥事,但是私有怎么半

这三个方案,理论上都可行,但是都有缺陷。

goproxy代理,本身并不解决从gitlab服务器获取私有项目代码的问题,也没有成熟的鉴权机制。因此比较适合静态公共代码。

​ 例子可以看: goproxy.cn/

nginx代理,同样不解决认证的问题,我配置了一个代理,ssl认证失败(弱鸡本鸡),理论上这个方案是最好的解决方案。

go replace,需要在每个项目中都添加,更新依赖也比较复杂。

所以采用的方案是,还是本地依赖。

目前网上的解决方案都是修改本地的git,配置,通过配置一些信息之类的,自行百度,但是还是又问题。最好还是搭建代理比较好,从代理层解决,可以参考上面的go proxy。

欢迎关注我们的微信公众号,每天学习Go知识

FveQFjN.jpg!web

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK