Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Go Modules 依赖

详解Go Modules 依赖解决

作者:serendipity_hky

本文主要介绍了Go Modules 依赖解决的实现,解决版本控制与GOPATH的痛点,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Go Modules是什么?

Go Modules 是 Go 语言的依赖解决方案

Go Modules 目前集成在 Go 的工具链中,只要安装了 Go,自然就可以使用 Go modules,Go modules 解决了 Go1.11 前的几个常见问题:
(1)Go 语言长久以来的依赖管理问题。
(2)“淘汰”现有的 GOPATH 的使用模式
(3)统一社区中的其它的依赖管理工具(提供迁移功能)

GOPATH 的工作模式

GOPATH下有三个文件夹:


bin:代表已经编译过的 go 语言的所有可执行程序。
pkg:存储默认文件,加快编译速度。
src:所有的源文件。

GOPATH 的弊端
(1)无版本控制概念。无法知道当前拉取的是哪个版本,也无法指定拉取自己的期望版本。
(2)无法同步一致第三方版本号。无法保证自己的版本与其他人的版本一致。
(3)无法指定当前项目引用的第三方版本号。

Go Modules模式

go mod命令

通过:go mod help
可以查看go mod命令

命令作用
go mod init生成go.mod文件
go mod download下载go.mod 文件中指明的所有依赖
go mod tidy整理现有的依赖
go mod graph查看现有的依赖结构
go mod edit编辑 go.mod 文件
go mod vendor导出项目所有的依赖到vendor目录
go mod verify校验一个模块是否被篡改过
go mod why查看为什么需要依赖某模块

go mod环境变量

通过 go env 命令查看环境变量:

(1)GO111MODULE

Go语言提供了GO111MODULE这个环境变量来作为Gomodules的开关,其允许设置以下参数:

可以通过来设置:go env -w G0111MODULE=on

(2)GOPROXY

这个环境变量主要是用于设置Go模块代理(Gomoduleproxy),其作用是用于使Go在后续拉取模块版本时直接通过镜像站点来快速拉取

GOPROXY 的默认值是:https://proxy.golang.org,direct
proxy·golang.org国内访问不了,需要设置国内的代理。

direct:用于指示Go回源到模块版本的源地址去抓取(比如GitHub等)

(3)GOSUMDB

它的值是一个Go checksum database,用于在拉取模块版本时(无论是从源站拉取还是通过Gomodule proxy拉取)保证拉取到的模块版本数据未经过篡改,若发现不一致,也就是可能存在篡改,将会立即中止。

GOSUMDB 的默认值为:sum.golang.org,在国内也是无法访问的,但是GOSUMDB 可以被Go模块代理所代理。

因此我们可以通过设置GOPROXY来解决,而先前我们所设置的模块代理goproxy.cn就能支持代理sum.golang.org,所以这一个问题在设置GOPROXY后,你可以不需要过度关心。

(4)GONOPROXY、GONOSUMDB、GOPRIVATE

Go Modules初始化项目

开启Go Modules

go env -w GO111MODULE=on

初始化项目

创建项目目录:在 E 盘下的 go_modules 文件夹下创建项目目录为 modules_test。
执行 Go modules 初始化,起一个当前项目的模块名称:go init github.com/go_modules/modules_test

初始化完成后,生成了 go.mod 文件:

打开 go.mod 文件:

在项目目录下编写源代码,创建 main.go 文件

package main

import (
    "fmt"
    "github.com/aceld/zinx/znet"
    "github.com/aceld/zinx/ziface"
)

//ping test 自定义路由
type PingRouter struct {
    znet.BaseRouter
}

//Ping Handle
func (this *PingRouter) Handle(request ziface.IRequest) {
    //先读取客户端的数据
    fmt.Println("recv from client : msgId=", request.GetMsgID(), 
              ", data=", string(request.GetData()))

    //再回写ping...ping...ping
    err := request.GetConnection().SendBuffMsg(0, []byte("ping...ping...ping"))
    if err != nil {
      fmt.Println(err)
    }
}

func main() {
    //1 创建一个server句柄
    s := znet.NewServer()

    //2 配置路由
    s.AddRouter(0, &PingRouter{})

    //3 开启服务
    s.Serve()
}

当前的 go_modules/modules_test 项目,依赖一个叫github.com/aceld/zinx库的,znet和ziface只是zinx的两个模块。

在 go_modules/modules_test 下执行:go get github.com/aceld/zinx/znet

此时 go.mod 文件被修改,并生成了 go.sum 文件:

(1)go.mod 文件:

(2)go.sum 文件
go.sum 文件详细罗列了当前项目直接或间接依赖的所有模块版本,并写明了模块版本的 SHA-256 哈希值以备 Go 在今后的操作中保证项目所依赖的那些模块版本不会被篡改

一个模块路径可能有如下两种:

h1:hash情况:是 Go modules 将目标模块版本的 zip 文件开包后,针对所有包内文件依次进行 hash,然后再把它们的 hash 结果按照固定格式和算法组成总的 hash 值。

go.mod hash情况:对 go.mod 文件做的hash

h1 hash 和 go.mod hash 两者,要不就是同时存在,要不就是只存在 go.mod hash。当 Go 认为肯定用不到某个模块版本的时候就会省略它的 h1 hash,就会出现不存在 h1 hash,只存在 go.mod hash 的情况。

修改模块的版本依赖关系

当前依赖的zinx版本是最新版本:

如果想要使用以前的旧版本,可以通过在项目目录下执行:

go mod edit -replace=zinx@v1.2.7=zinx@v0.0.0-20200221135252-8a8954e75100

此时,go mod文件:

replace关键字:用于将一个模块版本替换为另外一个模块版本。

到此这篇关于Go Modules 依赖解决的实现的文章就介绍到这了,更多相关Go Modules 依赖内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文