Linux系统安装Go1.11首次使用modules


因为最近都在研究Golang,而且从关注时的1.8到现在1.11已经更新好几个版本了。

Go 1.8版本中,如果开发者没有显式设置GOPATH,Go会赋予GOPATH一个默认值(在linux上为$HOME/go)。虽说不用再设置GOPATH,但GOPATH还是事实存在的,它在go 工具链中依旧发挥着至关重要的作用。

 

在1.10版本前当执行go get获取第三方代码包的时候,默认会放存放在$GOPATH/src下面。

而我们在代码里通过import导入包的时候,就按照import path去$GOPATH/src搜索相应的package。

在1.11的变化中加入的新功能modules “包依赖管理”,用起来比之前的dep更好用了。这里做一个简单的记录和测试;

系统环境:CentOS release 6.5 (Final) 2.6.32-431.el6.x86_64

Golang下载地址:https://dl.google.com/go/go1.11.linux-amd64.tar.gz

 

安装:

  1. wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz 
  2. tar xf go1.11.linux-amd64.tar.gz -C /opt 

 

添加环境变量:[这里直接不配置GOPATH路径了,在linux上为$HOME/go,我使用root用户,所以目录为/root/go]

vim /etc/profile  加入以下三行到文件最后面

  1. export GO111MODULE=on 
  2. export GOROOT=/opt/go 
  3. export PATH=$PATH:$GOROOT/bin 

说明export GO111MODULE=on是Go1.11中使用modules的一个开关,就是没有强制直接使用modules工具,毕竟也是新出来的;它有三个值auto、on、off;默认为auto,如果为空就是关闭,因为要使用它所以我直接在全局中加入此参数;

使配置生效;

  1. source /etc/profile 

查看当前的Go env

  1. [root@nginx-web opt]# go env 
  2. GOARCH="amd64" 
  3. GOBIN="" 
  4. GOCACHE="/root/.cache/go-build" 
  5. GOEXE="" 
  6. GOFLAGS="" 
  7. GOHOSTARCH="amd64" 
  8. GOHOSTOS="linux" 
  9. GOOS="linux" 
  10. GOPATH="/root/go"     //默认没有配置在这里,不同系统及用户不同 
  11. GOPROXY="" 
  12. GORACE="" 
  13. GOROOT="/opt/go" 
  14. GOTMPDIR="" 
  15. GOTOOLDIR="/opt/go/pkg/tool/linux_amd64" 
  16. GCCGO="gccgo" 
  17. CC="gcc" 
  18. CXX="g++" 
  19. CGO_ENABLED="1" 
  20. GOMOD="" 
  21. CGO_CFLAGS="-g -O2" 
  22. CGO_CPPFLAGS="" 
  23. CGO_CXXFLAGS="-g -O2" 
  24. CGO_FFLAGS="-g -O2" 
  25. CGO_LDFLAGS="-g -O2" 
  26. PKG_CONFIG="pkg-config" 
  27. GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build055060734=/tmp/go-build" 

#初始化一个mod环境,这里后面跟的是一个mod(modules)名称,名称可以随意。但是不能存在相同名字的。

  1. [root@nginx-web demo]# go mod init goDataTest 
  2. go: creating new go.mod: module goDataTest 

 

如果再次执行上面命令就有以下提示:[已经存在]

  1. [root@nginx-web demo]# go mod init goDataTest 
  2. go mod init: go.mod already exists 

 

查看当前目录下只有一个go.mod文件,而文件只有一行 goDataTest 就是我们定义的module名称。

  1. [root@nginx-web demo]# cat go.mod  
  2. module goDataTest 

 

接下来在当前目录下创建一个dbtest.go文件,内容如下:

 

  1. package main 
  2. import ( 
  3.     "database/sql" 
  4.     "fmt" 
  5.     _ "github.com/go-sql-driver/mysql" 
  6. func main() { 
  7.     db, err :sql.Open("mysql", "dba:123456@tcp(10.0.10.110:3306)/test?charset=utf8") 
  8.     //处理异常 
  9.     if err != nil { 
  10.         panic(err) 
  11.     } 
  12.     defer db.Close() 
  13.  
  14.     //查询数据 
  15.     rows, err :db.Query("select * from users") 
  16.     for rows.Next() { 
  17.         var ( 
  18.             id       int 
  19.             username string 
  20.             fullname string 
  21.             password string 
  22.             email    string 
  23.             group_id int 
  24.         ) 
  25.         //查询上面的所有 
  26.         err = rows.Scan(&id, &username, &fullname, &password, &email, &group_id) 
  27.         fmt.Println(id, username, fullname, password, email, group_id) 
  28.     } 

 

接下来就是build代码就好了。[这么简单?之前还要先下载依赖包才可以],此时执行go build dbtest.go 会提示需要的包不存在,无法build。

 

  1. [root@nginx-web demo]# go build dbtest.go  
  2. build goDataTest: cannot find module for path github.com/go-sql-driver/mysql 

需要先下载完第三方包后build才能成功。

 

现在使用代理即可完帮助代码自动下载相应的包:

 

关于 $GOPROXY

当我们使用go的时候,go默认会直接从代码库中去下载所需的相关依赖,GOPROXY 这个环境变量可以让我们控制自己从哪里去下载源代码,如果 GOPROXY 没有设置,go 会直接从代码库下载相关依赖代码。如果你像下面这样设置了这个环境变量,那么你就会通过 goproxy.io 下载所有的源代码。

  1. export GOPROXY=https://goproxy.io 

你可以通过置空这个环境变量来关闭,export GOPROXY=

如果要开机、全局生效的就要在/etc/profile中也加入即可。

查看当前系统中的变量,这里过滤GO的配置

  1. [root@nginx-web ~]# export|grep "GO" 
  2. declare -x GO111MODULE="on" 
  3. declare -x GOPROXY="https://goproxy.io" 
  4. declare -x GOROOT="/opt/go" 

见证奇迹的时候了,直接build上面的dbtest.go 代码,效果如下:

 

可以看到,它自动会下载导入的第三方包,并标记了所下载的版本,之前的go get 方法并不清楚包的版本,这里就有记录了。

 

如果我指定版本呢?直接修改go.mod文件中的1.4.0为1.3.0[此版本必须存在,可以参考github上的URL记录]

再次执行build时,可以看到如下效果,它又下载了1.3.0的包了。

  1. [root@nginx-web demo]# go build dbtest.go  
  2. go: finding github.com/go-sql-driver/mysql v1.3.0 
  3. go: downloading github.com/go-sql-driver/mysql v1.3.0 

查看默认的GOPATH路径,$HOME/go发现已经下载了两个包了。

 

再次试验,复制一份demo 并改名为demo1,并把目录下的go.mod 和go.sum文件删除,只保留一个dbtest.go代码文件即可;再次初始化一个.mod文件,这里名字为demo1

  1. cd demo1 
  2. go mod init demo1 

 

看图:它默认是使用latest版本的;仔细对比后面的h1的值会发现是包一样的;

 

go list -m输出的信息被称为 build list ,也就是构建当前module所要构建的所有相关package(及版本)的列表。

 
  1. [root@nginx-web demo1]# go list -m -json all 
  2.     "Path": "demo1", 
  3.     "Main": true, 
  4.     "Dir": "/test/demo1", 
  5.     "GoMod": "/test/demo1/go.mod" 
  6.     "Path": "github.com/go-sql-driver/mysql", 
  7.     "Version": "v1.4.0", 
  8.     "Time": "2018-06-03T12:45:54Z", 
  9.     "Dir": "/root/go/pkg/mod/github.com/go-sql-driver/mysql@v1.4.0", 
  10.     "GoMod": "/root/go/pkg/mod/cache/download/github.com/go-sql-driver/mysql/@v/v1.4.0.mod" 

 

其实此时哪怕把go.mod和go.sum删除了也可以正常build,那时因为系统已经下载回来对应的包了,所以删除也可以,但是删除了并不方便对代码的依赖和管理,毕竟版本的变化可能造成其它的问题。

 

 

修改版本,不如我直接vim修改快,而且还要注意这个"@"来接连版本号,替换配置文件中的空格.

 

  1. [root@nginx-web demo1]# go mod edit -require=github.com/go-sql-driver/mysql@v1.3.0 
  2. [root@nginx-web demo1]# cat go.mod  
  3. module demo1 
  4.  
  5. require ( 
  6.     github.com/go-sql-driver/mysql v1.3.0 
  7.     google.golang.org/appengine v1.1.0 // indirect 

 

对于go1.11版本也只是简单的试用了一下,感觉还是错,如果没有那个代理的话,那么这个modules在国内是用不上了,因为无法自动去下载代码中导入的包。

备注: 在使用Gosublime插件[我是在ubuntu系统中遇到]时可能提示未检查到GOPATH的问题,如果遇到这情况就配置一个GOPATH变量到/etc/profile中;

  1. export GOPATH=/root/go 

 

如果需要导入本地包时,在import里带上项目的名字,例如: