zoukankan      html  css  js  c++  java
  • golang包管理解决之道——go modules初探

    golang的包管理是一直是为人诟病之处,从golang1.5引入的vendor机制,到准官方工具dep,目前为止还没一个简便的解决方案。

    不过现在go modules随着golang1.11的发布而和我们见面了,这是官方提倡的新的包管理,乃至项目管理机制,可以不再需要GOPATH的存在。

    go module的初始化

    现在modules机制仍在早期阶段,所以golang提供了一个环境变量“GO111MODULE”,默认值为auto,如果当前目录里有go.mod文件,就使用go modules,否则使用旧的GOPATH和vendor机制,因为在modules机制下go get只会下载go modules,这一行为会在以后版本中成为默认值,这里我们保持auto即可,如果你想直接使用modules而不需要从GOPATH过度,那么把“GO111MODULE”设置为on。

    modules和传统的GOPATH不同,不需要包含例如src,bin这样的子目录,一个源代码目录甚至是空目录都可以作为module,只要其中包含有go.mod文件。

    我们就用一个空目录来创建我们的第一个module:

    要初始化modules,需要使用如下命令(假设已经安装配置好golang1.11):

    go mod init [module name]

    我们的module叫test,所以就是:

    go mod init test

    初始完成后会在目录下生成一个go.mod文件,里面的内容只有一行“module test”。

    包管理

    那么我们怎么进行包管理呢?别担心,当我们使用go build,go test以及go list时,go会自动得更新go.mod文件,将依赖关系写入其中。

    如果你想手动处理依赖关系,那么使用如下的命令:

    go mod tidy

    这条命令会自动更新依赖关系,并且将包下载放入cache。

    下面我们使用chromedp的一个简单example作为实验代码main.go,看下go modules是如何处理包的依赖关系的。

    我们手动运行go mod tidy:

    查找并下载包

    我们发现多了一个go.sum,我们看看它里面是什么内容:

    没错,你已经猜到了,这是我们直接引用的package和它自身需要的以来的版本记录,go modules就是根据这些去找到需要的packages的。

    顺带一提,如果我们不做任何修改,默认会使用最新的包版本,如果包打过tag,那么就会使用最新的那个tag对应的版本。

    下面我们使用go build来编译我们的代码:

    go build

    值得注意的是,新增了一个编译选项“-mod”,它有如下的可选值:

    go build -mod=readonly

    在这个模式下任何会导致依赖关系变动的情况都将导致build失败,前面提到过build能查找并更新依赖关系,使用这个选项可以检查依赖关系的变动。

    go build -mod=vendor

    意思是忽略cache里的包,只使用vendor目录里的版本。

    构建完成后目录结构如下:

    我们的代码成功构建了,包管理都由go modules替我们完成了。

    包的版本控制

    包管理的另外一项重要功能就是包的版本控制。modules同样可以做到。

    在介绍版本控制之前,我们要先明确一点,如果上层目录和下层目录的go.mod里有相同的package规则,那么上层目录的无条件覆盖下层目录,目的是为了main module的构建不会被依赖的package所影响。

    那么我们看看go.mod长什么样:

    module test
    
    require github.com/chromedp/chromedp v0.1.2

    如果有多个依赖,可以是这样的:

    module github.com/chromedp/chromedp
    
    require (
    	github.com/chromedp/cdproto v0.0.0-20180713053126-e314dc107013
    	github.com/disintegration/imaging v1.4.2
    	github.com/gorilla/websocket v1.2.0
    	github.com/knq/sysutil v0.0.0-20180306023629-0218e141a794
    	github.com/mailru/easyjson v0.0.0-20180606163543-3fdea8d05856
    	golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81
    )

    前面部分是包的名字,也就是import时需要写的部分,而空格之后的是版本号,版本号遵循如下规律:

    vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
    vX.0.0-yyyymmddhhmmss-abcdefabcdef
    vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef
    vX.Y.Z

    也就是版本号+时间戳+hash,我们自己指定版本时只需要制定版本号即可,没有版本tag的则需要找到对应commit的时间和hash值。

    默认使用最新版本的package。

    现在我们要修改依赖关系了,我们想使用chromedp 的v0.1.0版本,怎么办呢?

    只需要如下命令:

    go mod edit -require="github.com/chromedp/chromedp@v0.1.0"

    @后面加上你需要的版本号。go.mod已经修改了:

    module test
    
    require github.com/chromedp/chromedp v0.1.0

    我们还需要让go modules更新依赖关系,这里我们手动go mod tidy之后:

    注意颜色较深的那两行,我们已经切换到了v0.1.0版本了。

    go modules是一个很大的主题,以后我还将进一步介绍它。

    如果想进一步深入go modules的使用,可以阅读我的这篇文章:再探go modules:使用与细节

    因为go1.11刚发布不久,这篇文件作为探路,必定会有错误和疏漏,欢迎大家指正!

  • 相关阅读:
    网页中的JavaScript
    css颜色表示
    css文本属性
    css2选择器
    css3选择器
    Canvas练习
    Canvas
    CSS样式之语法
    css基础1
    php操作成功返回当前页并刷新
  • 原文地址:https://www.cnblogs.com/apocelipes/p/9534885.html
Copyright © 2011-2022 走看看