因为最近都在研究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
安装:
wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz
tar xf go1.11.linux-amd64.tar.gz -C /opt
添加环境变量:[这里直接不配置GOPATH路径了,在linux上为$HOME/go,我使用root用户,所以目录为/root/go]
vim /etc/profile 加入以下三行到文件最后面
export GO111MODULE=on
export GOROOT=/opt/go
export PATH=$PATH:$GOROOT/bin
说明:export GO111MODULE=on是Go1.11中使用modules的一个开关,就是没有强制直接使用modules工具,毕竟也是新出来的;它有三个值auto、on、off;默认为auto,如果为空就是关闭,因为要使用它所以我直接在全局中加入此参数;
使配置生效;
source /etc/profile
查看当前的Go env
[root@nginx-web opt]# go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/root/go" //默认没有配置在这里,不同系统及用户不同
GOPROXY=""
GORACE=""
GOROOT="/opt/go"
GOTMPDIR=""
GOTOOLDIR="/opt/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build055060734=/tmp/go-build"
初始化一个mod环境,这里后面跟的是一个mod(modules)名称,名称可以随意。但是不能存在相同名字的。
[root@nginx-web demo]# go mod init goDataTest
go: creating new go.mod: module goDataTest
如果再次执行上面命令就有以下提示:[已经存在]
[root@nginx-web demo]# go mod init goDataTest
go mod init: go.mod already exists
查看当前目录下只有一个go.mod文件,而文件只有一行 goDataTest 就是我们定义的module名称。
[root@nginx-web demo]# cat go.mod
module goDataTest
接下来在当前目录下创建一个dbtest.go文件,内容如下:
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "dba:123456@tcp(10.0.10.110:3306)/test?charset=utf8")
//处理异常
if err != nil {
panic(err)
}
defer db.Close()
//查询数据
rows, err := db.Query("select * from users")
for rows.Next() {
var (
id int
username string
fullname string
password string
email string
group_id int
)
//查询上面的所有
err = rows.Scan(&id, &username, &fullname, &password, &email, &group_id)
fmt.Println(id, username, fullname, password, email, group_id)
}
}
接下来就是build代码就好了。[这么简单?之前还要先下载依赖包才可以],此时执行go build dbtest.go 会提示需要的包不存在,无法build。
[root@nginx-web demo]# go build dbtest.go
build goDataTest: cannot find module for path github.com/go-sql-driver/mysql
需要先下载完第三方包后build才能成功。
现在使用代理即可完帮助代码自动下载相应的包:
关于 $GOPROXY
当我们使用go的时候,go默认会直接从代码库中去下载所需的相关依赖,GOPROXY 这个环境变量可以让我们控制自己从哪里去下载源代码,如果 GOPROXY 没有设置,go 会直接从代码库下载相关依赖代码。如果你像下面这样设置了这个环境变量,那么你就会通过 goproxy.io
下载所有的源代码。
export GOPROXY=https://goproxy.io
你可以通过置空这个环境变量来关闭,export GOPROXY=
如果要开机、全局生效的就要在/etc/profile中也加入即可。
查看当前系统中的变量,这里过滤GO的配置
[root@nginx-web ~]# export|grep "GO"
declare -x GO111MODULE="on"
declare -x GOPROXY="https://goproxy.io"
declare -x GOROOT="/opt/go"
见证奇迹的时候了,直接build上面的dbtest.go 代码,效果如下:
可以看到,它自动会下载导入的第三方包,并标记了所下载的版本,之前的go get 方法并不清楚包的版本,这里就有记录了。
如果我指定版本呢?直接修改go.mod文件中的1.4.0为1.3.0[此版本必须存在,可以参考github上的URL记录]
再次执行build时,可以看到如下效果,它又下载了1.3.0的包了。
[root@nginx-web demo]# go build dbtest.go
go: finding github.com/go-sql-driver/mysql v1.3.0
go: downloading github.com/go-sql-driver/mysql v1.3.0
查看默认的GOPATH路径,$HOME/go发现已经下载了两个包了。
再次试验,复制一份demo 并改名为demo1,并把目录下的go.mod 和go.sum文件删除,只保留一个dbtest.go代码文件即可;再次初始化一个.mod文件,这里名字为demo1
cd demo1
go mod init demo1
看图:它默认是使用latest版本的;仔细对比后面的h1的值会发现是包一样的;
go list -m输出的信息被称为 build list ,也就是构建当前module所要构建的所有相关package(及版本)的列表。
[root@nginx-web demo1]# go list -m -json all
{
"Path": "demo1",
"Main": true,
"Dir": "/test/demo1",
"GoMod": "/test/demo1/go.mod"
}
{
"Path": "github.com/go-sql-driver/mysql",
"Version": "v1.4.0",
"Time": "2018-06-03T12:45:54Z",
"Dir": "/root/go/pkg/mod/github.com/go-sql-driver/mysql@v1.4.0",
"GoMod": "/root/go/pkg/mod/cache/download/github.com/go-sql-driver/mysql/@v/v1.4.0.mod"
}
其实此时哪怕把go.mod和go.sum删除了也可以正常build,那时因为系统已经下载回来对应的包了,所以删除也可以,但是删除了并不方便对代码的依赖和管理,毕竟版本的变化可能造成其它的问题。
修改版本,不如我直接vim修改快,而且还要注意这个”@”来接连版本号,替换配置文件中的空格.
[root@nginx-web demo1]# go mod edit -require=github.com/go-sql-driver/mysql@v1.3.0
[root@nginx-web demo1]# cat go.mod
module demo1
require (
github.com/go-sql-driver/mysql v1.3.0
google.golang.org/appengine v1.1.0 // indirect
)
对于go1.11版本也只是简单的试用了一下,感觉还是错,如果没有那个代理的话,那么这个modules在国内是用不上了,因为无法自动去下载代码中导入的包。
在使用Gosublime插件[我是在ubuntu系统中遇到]时可能提示未检查到GOPATH的问题,如果遇到这情况就配置一个GOPATH变量到/etc/profile中;
export GOPATH=/root/go
如果需要导入本地包时,在import里带上项目的名字,例如: