一块儿弄明白go的依赖管理 Go Modues/ GOPATH

一块儿弄明白go的依赖管理 Go Modues/ GOPATH

不要吝啬你的批评与感悟,敬请留言,咱们一块儿进步。mysql

若是你有过如下问题,欢迎阅读文章,提出意见与建议git

  1. go mod 怎么使用
  2. GOPATH是什么
  3. GO111MODULE="" 这个参数决定了什么
  4. go get、go download 有什么区别

依赖管理工具

用过Java 的同窗都知道,对依赖的管理从原始的手动引入jar包,到使用maven等进行自动化管理工具去引入第三方依赖,使用别人已经开发好的优秀工具。若是使用过Python的同窗可能会熟练的使用pip install 第三方的工具包。Java 和Python的第三方工具包都是集中式管理的,使用maven 或者是pip 都是从对应的管理中心下载更新依赖。固然还有 npm、yarn、gradle等其余语言的依赖版本工具。github

在go语言中,第三方依赖的管理工具通过了一个漫长的发展过程。在GO1.11 发布以前govendor、dep等工具百花齐放。知道go mod 出现,开始一统天下。go 的依赖很是简单粗暴,只要依赖源码就能够了。例如:golang

import  "github.com/jinzhu/gorm"
复制代码

github.com/jinzhu/gorm 就是gorm的GitHub项目路径。web

GOPATH时期

Go 在1.11 以前使用GOPATH模式进行依赖的管理。安装部署go环境,使用go 进行开发的时候强制被要求要设置GOPATH(固然安装过程当中也会默认指定$GOPATH=~/go)。 要在GOPATH路径下新建 src /bin /pkg文件夹。sql

go
├── bin  # 存储go编译生成的二进制可执行文件,通常会把该路径配置到PATH中,PATH=$PATH:$GOPATH/bin
├── pkg  # 存储预编译的目标文件,以加快后续的编译速度 
└── src  # 存储Go的源代码,通常以$GOPATH/src/github.com/foo/bar的路径存放
复制代码
➜  go go env |grep GOPATH
GOPATH="/Users/bytedance/go"
复制代码

在这种模式下,若是使用go get 拉取外部依赖会自动下载并安装到$GOPATH 目录下。npm

这种模式下,go get没有版本管理的概念,没法处理依赖不一样版本的问题,由于同一个依赖都存在同一个路径下面。网络

在Go官方尚未推出Go Modules 的时候,go的依赖管理工具可谓是 百花齐放,例如 govendordep,可是最终Go Modules发布,平息了诸侯割据的局面。app

GO Modules

Go1.11 开始推出Go Modules ,Go1.13开始再也不推荐使用GOPATH。意思就是说你能够在任何路径下存放你的Go源码文件, 不用再像之前同样非得放到$GOPATH/src中。 每个go 项目 都是一个 Modules。vgo 是Go Modules的前身。maven

在Go Modules环境下出现了一个很重要的环境变量GO111MODULE

➜ ~ go env
GO111MODULE="auto"
GOPROXY="https://proxy.golang.org,direct"
GONOPROXY=""
GOSUMDB="sum.golang.org"
GONOSUMDB=""
GOPRIVATE=""
复制代码

若是要对go 的环境变量进行设置,可使用

go env -w GO111MODULE=on  # 设置go 环境变量
go env -u # 恢复初始设置

复制代码

GO111MODULE

GO111MODULE 这个环境变量是用来做为使用Go Modules 的开关。能够说这个变量是历史产物,颇有肯能会在未来Go的新版本中去除掉。

GO111MODULE="auto" # 只要项目包含了go.mod 文件的话就启用Go modules, 在Go1.11-1.14 中是默认值
GO111MODULE="on"   # 启用Go Modules
GO111MODULE="off"  # 禁用Go Modules, 对老的项目进行兼容
复制代码

GOPROXY

GOPROXY 是Go Modules的代理,能够经过镜像站点快速拉取(集中式的概念?),能够设置多个代理。

GOPROXY="https://proxy.golang.org,direct"
复制代码

direct的意思是若是经过代理获取不到go get 就会经过源地址直接去抓取

go mod

建立Go Modules的基本命令

➜  ~ go mod
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.
# 全部的go commands 都支持 modules。
Usage:

        go mod <command> [arguments]

The commands are:

        download    download modules to local cache
        edit        edit go.mod from tools or scripts
        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
        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 init

在当前目录初始化一个新的module, 就是说将该目录下的工程文件初始化为一个go module.

若是当前目录在GOPATH中,这条命令无需传入参数,参数默认为 GOPATH/src 到该目录的相对路径。

➜  demo pwd
/Users/bytedance/go/src/github.com/airren/demo
➜  demo go mod init
go: creating new go.mod: module github.com/airren/demo
➜  demo ls
go.mod
➜  demo cat go.mod
module github.com/airren/demo

go 1.14
➜  demo
复制代码

若是当前目录不在GOPATH中,要手动指定module的名字

➜  gotest pwd                                 
/Users/bytedance/Desktop/gotest
➜  gotest go mod init       # 若是不在GOPATH路径下                  
go: cannot determine module path for source directory /Users/bytedance/Desktop/gotest (outside GOPATH, module path must be specified)

Example usage:
        'go mod init example.com/m' to initialize a v0 or v1 module
        'go mod init example.com/m/v2' to initialize a v2 module

Run 'go help mod init' for more information.
➜  gotest go mod init github.com/airren/gotest 
go: creating new go.mod: module github.com/airren/gotest
➜  gotest cat go.mod 
module github.com/airren/gotest

go 1.14
➜  gotest 
复制代码

go mod download

go mod download 命令会把package下载到 GOPATH/pkg/mod路径下,下载时要指定版本能够用@latest。能够任意路径下使用go mod download

➜  jinzhu pwd
/Users/bytedance/go/pkg/mod/github.com/jinzhu
➜  jinzhu ls
gorm@v1.9.11-0.20190912141731-0c98e7d712e2    inflection@v1.0.0
gorm@v1.9.12                                  now@v1.0.1
inflection@v0.0.0-20180308033659-04140366298a now@v1.1.1
➜  jinzhu go mod download -x github.com/jinzhu/gorm@v1.9.8  # 要指定版本
➜  jinzhu ls
gorm@v1.9.11-0.20190912141731-0c98e7d712e2    inflection@v1.0.0
gorm@v1.9.12                                  now@v1.0.1
gorm@v1.9.8                                   now@v1.1.1
inflection@v0.0.0-20180308033659-04140366298a
➜  jinzhu cd gorm@v1.9.8
复制代码

import

import 导入的是文件存储的相对路径(不能使用绝对路径),并非package的name,可是在调用Function的时候使用的是package的name。

import 首先会从GOPATH/src 中寻找,若是是以./ 或者 ../ 开头的import 直接去对应的相对路径寻找。

import 时候是不区分大小写的,因此在go项目中folder的name尽可能是小写,能够有下滑线_, 可是packagename必定不能有\_,不然golint会有提示。

文件结构如图所示

gotest
├── format_print
│   └── colorprintpath.go  # 文件名并不影响 import
└── sdemo
    ├── demo.go
复制代码

colorprintpath.go

package colorprintfile // 调用方法时候经过package name 调用
import "fmt"
// NewPirnt is the new format print  公开方法要有注释
func NewPrint(content string) {
 fmt.Printf("This is the content: %v \n", content)
}
复制代码

demo.go

package main
import  "../format_print"  // import 使用的是相对路径
func main(){
 colorprintfile.NewPrint("hello")  // 调用package中的公开方法
}
复制代码

若是使用了go mod, 在项目文件下有了go.mod, 文件中会有

module github.com/airren/gotest
复制代码

此时就不能使用相对路径引用package, 要经过modules的方式引用

package main
import  "github.com/airren/gotest/format_print"
func main(){
 colorprintfile.NewPrint("hello")  // 调用package中的公开方法
}
复制代码

go get

能够在任意路径下执行go get

  • 用于从远程代码仓库(github, gitlab,gogs)上下载并安装代码包

  • 支持的代码版本控制系统有: Git , Mercurial(hg),SVN, Bazaar

  • 指定的代码包会被下载到$GOPATH中包含的第一个工做区的src目录中,而后再安装

    经常使用参数

    -d # 只执行下载动做,而不执行安装动做
    -fix # 在下载代码包后先执行修正动做,然后再进行编译和安装
    -u # 利用网络来更新已有的代码包及其依赖包
    -x # 显示过程
    复制代码

例如使用go get 获取 gorm。 经过-x 参数能够展现详细的过程。

➜  ~ go get -u -x github.com/jinzhu/gorm
cd .
git clone -- https://github.com/jinzhu/gorm /Users/bytedance/go/src/github.com/jinzhu/gorm
cd /Users/bytedance/go/src/github.com/jinzhu/gorm
git submodule update --init --recursive
cd /Users/bytedance/go/src/github.com/jinzhu/gorm
git show-ref
cd /Users/bytedance/go/src/github.com/jinzhu/gorm
git submodule update --init --recursive
cd /Users/bytedance/go/src/github.com/jinzhu/inflection
git config remote.origin.url
cd /Users/bytedance/go/src/github.com/jinzhu/inflection
git pull --ff-only
cd /Users/bytedance/go/src/github.com/jinzhu/inflection
git submodule update --init --recursive
cd /Users/bytedance/go/src/github.com/jinzhu/inflection
git show-ref
cd /Users/bytedance/go/src/github.com/jinzhu/inflection
git submodule update --init --recursive
WORK=/var/folders/pz/w7jm4wm933lcspm82kff26600000gn/T/go-build644292157
复制代码

若是在具备go.mod 的项目的文件夹下使用go get , 会将对应的依赖以及版本写入go.mod, go.sum 是自动生成的,具体介绍能够查看https://studygolang.com/articles/25658

➜  gotest cat go.mod 
module github.com/airren/gotest

go 1.14
➜  gotest cat go.sum 
cat: go.sum: No such file or directory
➜  gotest go get -u github.com/jinzhu/gorm/    
go: github.com/jinzhu/gorm upgrade => v1.9.12
➜  gotest cat go.mod 
module github.com/airren/gotest

go 1.14

require github.com/jinzhu/gorm v1.9.12 // indirect
➜  gotest cat go.sum 
github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q=
github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=

复制代码

不要吝啬你的批评与感悟,敬请留言,咱们一块儿进步。

参考文献:

https://github.com/golang/go/wiki/Modules

https://blog.golang.org/using-go-modules

https://juejin.im/post/5e57537cf265da57584da62b

https://learnku.com/go/t/39086

https://studygolang.com/articles/25658

相关文章
相关标签/搜索