我自己尝试 go module
的使用,是在 Ubuntu Server 18.04.4 LTS 64bit
下进行。
请注意当前用户是否有足够的权限,我是自己的学习环境,偷懒使用了 root
权限。
#下载压缩包
wget https://dl.google.com/go/go1.14.linux-amd64.tar.gz
#解压到 /usr/local/ 目录下(如果压缩包已直接下载到了 /usr/local/ 目录中,此步骤可以忽略)
tar -xvf go1.14.linux-amd64.tar.gz -C /usr/local/
#启动编辑模式,编辑配置文件
vim ~/.profile
#将下面2行代码黏贴到文件的最末尾(需要按Insert键或者i键)
export GOROOT=/usr/local/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
#保存并退出。(按ESC键,按冒号键,键入wq,回车)
#使文件立刻生效
source ~/.profile
#测试是否安装成功
go env
#如果能看到各种配置信息,说明已安装成功
在 shell 中键入命令:
go env
想使用 go mod
,检查一下 GO111MODULE
这个属性的值必须为 on
。(Go1.12 开始,默认 GO111MODULE=on
)
golang 项目中使用第三方模块的时候,需要以URL绝对路径格式引入这些包。
例如:import github.com/gin-gonic/gin
以 域名/组名/模块
的 URL 绝对路径格式引入这个第三方模块。
编译时,如果检测到没有安装某个第三方模块,go 会自动去该 URL 中拉取模块。
直接去国外网站拉取模块,经常会导致时间过长甚至超时失败。万般无奈,只能设置一个能用的镜像代理。
在 shell 中,分别执行下面2行 shell 代码:
go env -w GOPROXY=https://goproxy.cn,direct
source ~/.profile
Go1.11 开始,官方就推荐使用 Go Module 对工程进行管理。但下载模块的时候,还是会将下载到的模块往 GOPATH 路径中放。
Ubuntu Server 中,如果不指定 GOPATH 的路径,GOPATH 的默认路径是当前用户的家目录下的 go 文件夹。例如,当前用户是 root,那么默认的 GOPATH 路径就是:/root/go
。
模块存放在本地,不使用远程仓。
设计思路:
1.文件夹 myGoModTest 作为项目的根目录。
2.在根目录中新建两个文件夹 main 和 calc。
3.最终实现在 main/main.go
中引入 calc/calc.go
中的函数。
mkdir myGoModTest
cd myGoModTest
go mod
初始化是 shell 命令,语法:go mod init [ProjectName]
其中,ProjectName 可以是不带域名格式的简洁模块名声明,也可以是 域名/组名/模块
的格式。(官方推荐以 域名/组名/模块
的方式来命名)
键入 shell 命令:
go mod init myGoModTest
mkdir main
mkdir calc
启动编辑模式:
cd calc
vim go.mod
将下面2行代码黏贴到文件中:
module calc
go 1.14
保存并退出。
启动编辑模式:
vim calc.go
将下面的代码黏贴到文件中:
package calc
func Add(a, b int) int {
return a + b
}
保存并退出。
Go 程序的入口只能是 main 包中的 main() 函数,项目中所需的所有依赖,都必须写在 main() 函数所在的同级目录下的 go.mod 文件中。
启动编辑模式:
vim go.mod
将下面的代码黏贴到文件中:
module main
go 1.14
require github.com/calc v0.0.0
replace github.com/calc v0.0.0 => ../calc
保存并退出。
启动编辑模式:
vim main.go
将下面的代码黏贴到文件中:
package main //声明这个是main包
import (
"fmt"
"github.com/calc"
)
func main() {
result := calc.Add(10, 20)
fmt.Println("result =", result)
}
最终的目录结构:
go run
和 go build
测试结果:
本地模块配合使用 Web 框架 gin
,在浏览器上呈现一个类似 Hello world 的文字信息。
1.新建一个根目录,名称为 myGinTest。
2.在根目录下新建一个 main.go 文件,将这个模块声明为 main 包,作为项目的启动入口。
3.在根目录下新建一个子目录 controllers,controllers 中存放一个 users.go 模块。
4.main 包中的 main() 函数将引入 controllers/users.go 模块中的函数。
5.将信息输出到网页上。
1.键入 shell 命令:
mkdir myGinTest
cd myGinTest
2.初始化项目的 shell 命令:
go mod init myGinTest
3.编辑 main.go 模块:
键入 shell 命令:
vim main.go
将下面的代码黏贴到 main.go 文件中:
package main
import (
"github.com/controllers"
"github.com/gin-gonic/gin"
"fmt"
)
func main() {
result := controllers.Hello()
fmt.Println("result =",result)
r := gin.Default()
r.GET("/user", func(c *gin.Context){
c.JSON(200, gin.H{
"message": result,
})
})
r.Run(":8888")
}
1.进入 controllers 目录。
2.初始化 controllers 模块的 shell 命令:
go mod init controllers
3.编辑 users.go 模块,将下面的代码黏贴到 main.go 文件中:
package controllers
func Hello() string {
return "Hello user, welcome! It's a successful message."
}
将下面的代码黏贴到 go.mod 中:
module myGinTest
go 1.14
require (
github.com/controllers v0.0.0
)
replace github.com/controllers v0.0.0 => ./controllers
在根目录下,执行 shell 指令:go run main.go
。可以看到,go 会去 github 上把最新版本的 gin 模块,整个拉取下来:
再次查看根目录下的 go.mod 文件,可以看到在 require 中,自动添加了 github.com/gin-gonic/gin v1.5.0 // indirect
这一行。
可以看到,上图的目录结构中,每一个文件夹下面都必须要有一个 go.mod
文件!
每个文件夹下都必须要有一个 go.mod 文件存在,且文件中的第一行必须声明模块名!
例如:
根目录 myGoModTest 文件夹下的 go.mod 文件,第一行声明了模块名 module myGoModTest
;
calc 目录下的 go.mod 文件,第一行声明了模块名 module calc
;
main 目录下的 go.mod 文件,第一行声明了模块名 module main
;
如果没有声明模块名,就会报如下错误:
go: cannot determine module path for source directory /root/myGoModTest/main (outside GOPATH, module path must be specified)
示例中,我把 main() 函数写在了 main 文件夹下的 main.go 文件中,并在 main.go 的第一行声明了它是一个 main 包。
main() 函数作为 Golang 程序的唯一入口,项目所需的依赖也是从入口的时候加载的。那么,就需要把所涉及的依赖都写在 main() 函数所在的同级目录下的 go.mod 文件中。
除了模块名不需要以域名格式开头(不建议这么做),其余 import
、require
、replace
,都必须以域名或 IP 格式开头。
使用 go mod
模式引入模块,无论是引入本地模块还是远程代码仓上的模块。只要是引入模块,那么:go.mod 中的 require 格式、replace、go 文件中的 import,都必须符合:域名(IP)/组名/模块 版本信息号
。(没有写组名可以省略不写)
go 文件中的 import 格式必须符合:域名(IP)/组名/模块
。(没有写组名可以省略不写)
例如,要引入 github 上的 gin 框架。
go.mod 中就要写成:require github.com/gin-gonic/gin v1.5.0 // indirect
。(现代版本的 go mod 已经相当智能化了,就算 go.mod 中没有写这行,代码一运行,就会自动把这行信息添加到 go.mod 的 require 中)
go 文件中的 import 要写成:import "github.com/gin-gonic/gin"
。
引入本地模块,go.mod 中的 require 也必须符合 域名(IP)/组名/模块 版本信息号
这一规范。
例如 4.4 示例中的 require github.com/controllers v0.0.0
或其他组名下的模块 require github.com/Barry/calc v0.0.0
。
可以看到,最后都跟了 v+版本编号
这一版本信息号的格式来结尾。
域名/组名/模块
方式来命名模块官方推荐使用 域名/组名/模块
的格式来命名模块,防止不同包的项目名冲突的问题。
举个例子:张三和李四都有一个名叫 studygo 的项目,那么这两个包的路径就会是:
go mod init github.com/zhangsan/studygo
go mod init github.com/lisi/studygo
我自己有个个人案例,就可以命名成为:go mod init github.com/Barry/goDemo
有些代码懒得放到远程代码仓上去,但引入模块的路径格式必须符合域名规范,此时需要使用 replace
。其作用是把公网域名替换为本地路径,并引导编译器去该本地路径中寻找模块。
程序的入口在根目录下的 main.go 中。
controllers 目录是项目的本地模块包,里面包含了一个本地子模块 users.go
可以看到,即使是引入本地模块,也必须符合 域名/组名/模块 版本信息号
规范。
格式:replace xxx.com/groupName/moduleName => localPath
。
这个模块我懒得放到远程代码仓中去,那就需要把公网域名替换成为本地路径。(注意路径)
主要是参考了这两位大佬的教程,我是综合这两篇文章,慢慢折腾出来的:
https://segmentfault.com/q/1010000020696591
https://blog.csdn.net/kevinh531/article/details/88691870