第八章 Go项目开发与编译
作者:李骁
8.1 项目结构
Go的工程项目管理非常简单,使用目录结构和包名来确定工程结构和构建顺序。
环境变量GOPATH在项目管理中非常重要,想要构建一个项目,必须确保项目目录在GOPATH中。而GOPATH可以有多个项目用";"分隔。
Go 项目目录下一般有三个子目录:
src存放源代码
pkg编译后生成的文件
bin编译后生成的可执行文件
我们重点要关注的其实就是src文件夹中的目录结构。
为了进行一个项目,我们会在GOPATH目录下的src目录中,新建立一个项目的主要目录,比如我写的一个WEB项目《使用gin快速搭建WEB站点以及提供RESTful接口》。 https://github.com/ffhelicopter/tmm 项目主要目录“tmm”: GOPATH/src/github.com/ffhelicopter/tmm 在这个目录(tmm)下面还有其他目录,分别放置了其他代码,大概结构如下:
src/github.com/ffhelicopter/tmm
/api
/handler
/model
/task
/website
main.gomain.go 文件中定义了package main 。同时也在文件中import了
2个自定义包。
上面的目录结构是一般项目的目录结构,基本上可以满足单个项目开发的需要。如果需要构建多个项目,可按照类似的结构,分别建立不同项目目录。
当我们运行go install main.go 会在GOPATH的bin 目录中生成可执行文件。
8.2 使用godoc
在程序中我们一般都会注释,如果我们按照一定规则,godoc工具会收集这些注释并产生一个技术文档。
命令行下进入目录下并输入命令: godoc -http=:6060 -goroot="."
然后在浏览器打开地址:http://localhost:6060
然后你会看到本地的 Godoc 页面,从左到右一次显示出目录中的包。 
8.3 Go程序的编译
在Go语言中,和编译有关的命令主要是go run ,go build , go install这三个命令。
go run只能作用于main包文件,先运行compile 命令编译生成.a文件,然后 link 生成最终可执行文件并运行程序,这过程的产生的是临时文件,在go run 退出前会删除这些临时文件(含.a文件和可执行文件)。最后直接在命令行输出程序执行结果。go run 命令在第二次执行的时候,如果发现导入的代码包没有发生变化,那么 go run 不会再次编译这个导入的代码包,直接进行链接生成最终可执行文件并运行程序。
go install用于编译并安装指定的代码包及它们的依赖包,并且将编译后生成的可执行文件放到 bin 目录下(GOPATH/bin),编译后的包文件放到当前工作区的 pkg 的平台相关目录下。
go build用于编译指定的代码包以及它们的依赖包。如果用来编译非main包的源码,则只做检查性的编译,而不会输出任何结果文件。如果是一个可执行程序的源码(即是 main 包),这个过程与go run 大体相同,除了会在当前目录生成一个可执行文件外。
使用go build时有一个地方需要注意,对外发布编译文件如果不希望被人看到源代码,请使用go build -ldflags 命令,设置编译参数-ldflags "-w -s" 再编译后发布。避免使用gdb来调试而清楚看到源代码。

8.4 Go modules 包依赖管理
Go 1.11 新增了对模块的支持,希望借此解决“包依赖管理”。可以通过设置环境变量 GO111MODULE来开启或关闭模块支持,它有三个可选值: off、 on、 auto,默认值是 auto。
GO111MODULE=off
无模块支持,go 会从 GOPATH 和 vendor 文件夹寻找包。
GO111MODULE=on
模块支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod下载依赖。
GO111MODULE=auto
在 GOPATH/src外面且根目录有 go.mod文件时,开启模块支持。
在使用模块的时候, GOPATH是无意义的,不过它还是会把下载的依赖储存在 GOPATH/pkg/mod 中。
运行命令,go help mod ,我们可以看到mod的操作子命令,主要是init、 edit、 tidy。
命令含义: download 下载依赖的module到本地cache edit 编辑go.mod文件 graph 打印模块依赖图 init 在当前文件夹下初始化一个新的module, 创建go.mod文件 tidy 增加丢失的module,去掉未用的module vendor 将依赖复制到vendor下 verify 校验依赖 why 解释为什么需要依赖
为了使用modules来管理项目,我们可以以下几个步骤来操作:
(1)首先需要设置GO111MODULE ,这里我们设置为auto。
(2)考虑和原来GOPATH有所隔离,新建立了一个目录D:\gomodules来存放modules管理的项目。
(3)在D:\gomodules下建立ind项目,建立对应的目录,D:\gomodules\ind
(4)在ind目录中,我们编写了该项目的主要文件main.go
1、第一次需要我们运行init命令初始化:
D:\gomodules\ind>go mod init ind
go: creating new go.mod: module ind
可以在ind目录看到新生成了一个文件:go.mod ,这个modules名字叫ind。
2、接下来我们运行go mod tidy 命令,发现如下图一样出现报错,这主要是众所周知的网络原因,由于这里主要是golang.org/x下的包,所以可以简单使用replace命令来解决这个问题,如果是其他厂商的依赖包,还是优先解决网络问题。
然后重复运行go mod tidy ,如果出错在使用replace,直到能正常运行go mod tidy 命令完成。
go mod edit -replace=old[@v]=new[@v]
注意:replace版本号可以在错误信息中看到。
D:\gomodules\ind>go mod edit -replace=golang.org/x/[email protected]=github.com/golang/[email protected]

3、我们看到在ind目录下面多了2个文件,分别是go.mod和go.sum。
go.mod文件
go.mod文件可以通过require,replace和exclude语句使用的精确软件包集。
(1)require语句指定的依赖项模块
(2)replace语句可以替换依赖项模块
(3)exclude语句可以忽略依赖项模块
go.sum文件
打开目录GOPATH/pkg/mod,我们可以看到这个项目下的依赖包都下载过来了。
本书《Go语言四十二章经》内容在github上同步地址:https://github.com/ffhelicopter/Go42
虽然本书中例子都经过实际运行,但难免出现错误和不足之处,烦请您指出;如有建议也欢迎交流。 联系邮箱:[email protected]
Last updated
Was this helpful?