即使你会Golang,也不一定明白的GOPATH,GOROOT,GO111MODULE和GOPROXY
- 写在前面
- 国内镜像配置
- 开始Hello World
- 简析Golang的依赖管理
- 写在最后
写在前面
近几年,Golang乘着云计算、区块链的东风,快速开始风靡互联网,越来越多的人开始学习Golang,网上也有很多关于Golang的教学,但现在都已经1.15了,很多网上的视频还是1.9…殊不知这几年,虽然Golang的语法几乎没变,但Golang以往被诟病的依赖管理的问题,已经全面解决。而这些设置,在你开始Hello World前,就应该了解并设置好。
但很遗憾这么基础的知识,我在网上搜了很多,却没有非常明确的信息。甚至很多会使用Golang的开发者,一提到GOPATH,GOROOT这些环境变量,也是非常头痛,完全不懂。
可能你看的教程中还在设置GOROOT、GOPATH,当然设置这些都没错,但现在已经升级了,有更好的设置方式,所以你应该更全面了解这些事而非人云亦云。
可能你是编程大神,但不了解golang,亦或者你只是刚学习Hello World的小白,请先看完这篇文章,相信会对你学习Golang有着莫大的帮助。
国内镜像配置
首先Golang的版本问题,建议安装1.13及更高的,如果是之前的版本,不是历史遗留问题最好升级。
安装好Golang后,我们用下面的命令看一下Golang的环境
$ go env
请大家记住这四个环境变量,GO111MODULE,GOPROXY,GOROOT和GOPATH。在老一点的教程里,可能会告诉你,要设置环境变量,GOPATH和GOROOT和PATH,但我要做的第一件事,就是先修改GO111MODULE和GOPROXY。打开终端,使用以下命令
$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct
设置代理的原因,我相信大家很清楚如果在国内直接从谷歌服务器或者github上下载项目是什么结果,所以先设置好代理,以后在下载第三方包的时候会非常方便。
接下来,你可以继续设置GOPATH和GOROOT,当然也可以不设置,原因我后面会说,但PATH最好还是设置,毕竟那是方便全局使用命令的。
开始Hello World
为了方便大家理解,我使用GoLand,用两种方式新建项目。比较推荐第二种。
第一种就是比较传统的方式创建Go项目。众所周知(如果你不知道,可以看第三部分),Golang项目应该放在GOPATH下,安装Golang以后,GOPATH如果不设置,应该和GOROOT一样。并且GOPATH下应该有src,bin和pkg三个目录。
点击File-New-project
你可能会说,不是之前没设置GOPATH吗,或者新建的文件是在GOPATH下吗?那明确的告诉你,这个项目的文件夹可以在任何地方,只需要在设置一个项目GOPATH就可以。创建完以后,打开File-Settings,找到GOPATH,去掉全局的GOPATH,选取你刚刚创建的目录为新的项目GOPATH即可。
如果用这种方式运行Golang,如果你的main函数是按照文件编译的,并且其中没有其他的引用可以直接运行,但你的函数是按包来编译,或者引入了其他包的函数结构体等,都是无法运行的,例如将目录变成这样
可以看到,我将main文件放入到main包中,此时直接运行,会报错
can’t load package: package main is not in GOROOT
这个问题我找了好久都没有满意的解决方案,原因我后面会说,具体解决方法是:
在terminal中运行命令
set GO111MODULE=off
这样只会影响你当前的环境,而不会影响你一开始设置的大环境。而且在Edit Configurations中,将Environment添加设置GO111MODULE=off
此时即可运行。其实这样做是不符合Golang设计的初衷的,但对于大部分的开发者而言,他们更不习惯把所有的项目都放在一个GOPATH下。
第二种方式是比较推荐的,就是直接创建一个go module项目。
此时创建的项目,没有任何限制,也不需要在GOPATH下,相当于之前在src下创建的目录,可以直接创建main包,写main函数,运行,一气呵成。
你可以看到使用go module创建的项目会多一个go.mod,如果你使用go get命令下载一个第三方包,会多一个go.sum,由于我们之前设置过GOPROXY,下载会变得非常流畅。
简析Golang的依赖管理
知其然还要知其所以然,我在网上也看过一些关于GOPATH,GOROOT,go module的解析,但感觉说的比较散,这也是我写这篇文章的原因。一方面,希望大家可以通过这篇文章能够进一步了解Golang的依赖管理,另一方面我自己也可以进一步总结我看到的资料。
Golang的依赖管理,经历了三个阶段,最初就是使用GOPATH,这也是大部分教程会让你配置GOPATH的原因。当时官方建议只有一个GOPATH,大家把项目都放到GOPATH下,而且GOPATH下需要src,bin,pkg三个文件夹,src用来放源码,bin目录用来放编译好好的可执行文件,pkg用来放编译过后引用的第三方包。
如果你用go get命令下载第三方包,那么会下载到src目录下,引用的时候,golang解释器回去GOROOT和GOPATH的src下找。
但这样做显然有问题,如果项目A和项目B都在GOPATH下,同时都引用了第三方包C,但一个引用C1.0版本,一个引用了C2.0版本,按照这种情况,ABC都在src目录下,如何区分C的版本呢?
为了解决这个问题,Golang的依赖管理出现了第二个阶段,使用vendor目录。在各自的项目下创建一个vendor目录,将第三方依赖放到vendor目录下,解释器也会优先去找vendor目录下的第三方包,这样就可以解决问题。常用的一些第三方依赖包,也就是用来管理vendor的。这个关系就很像pip之于python,maven之于java。但这仍然无法解决很难用的GOPATH。
好在官方意识到了这个问题,也就到了第三个阶段,使用go module。使用go module已经完全不依赖于GOPATH了,可以说完美解决了解决第三方依赖的问题,而且很多Golang的项目也在往go module迁移。
当然最大的网络问题,也有GOPROXY帮我们解决,google可算为Golang操碎了心,希望Golang以后可以越来越火。
写在最后
以上内容,操作源于自己的操作和经验,原理来自一个谷歌大佬的课程,没有任何权威性,如有问题,自己负责。