第八章 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.go

main.go 文件中定义了package main 。同时也在文件中import了

2个自定义包。

上面的目录结构是一般项目的目录结构,基本上可以满足单个项目开发的需要。如果需要构建多个项目,可按照类似的结构,分别建立不同项目目录。

当我们运行go install main.go 会在GOPATH的bin 目录中生成可执行文件。

8.2 使用godoc

在程序中我们一般都会注释,如果我们按照一定规则,godoc工具会收集这些注释并产生一个技术文档。

命令行下进入目录下并输入命令: godoc -http=:6060 -goroot="."

然后在浏览器打开地址:http://localhost:6060

然后你会看到本地的 Godoc 页面,从左到右一次显示出目录中的包。 godoc.png

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来调试而清楚看到源代码。

ch5.png

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]

go mod tidy 命令

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?