Go语言学习五——工程管理

Posted 自由水鸟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go语言学习五——工程管理相关的知识,希望对你有一定的参考价值。

在之前的文章中我们已经了解了Go语言的基本使用,已经可以使用Go语言来编程了。在实际应用中,一个项目除了编码外,还需要考虑工程管理的方方面面的问题,例如:工程组织、依赖管理、编译打包、单元测试、部署上线、持续集成等。只有这些都具备了,才能真正应用到生产环境。持续集成是一个比较大的话题,单元测试也相对独立,这两个暂且不表,本次我们先来看一下Go语言的工程组织、编译打包、依赖管理、部署上线。

一. 工程组织

workspace

在go的世界里,workspace是我们进行项目开发时的工作空间。它指的是一个目录,该目录下通常包含三个子目录,完整的目录结构如下:

~/workspace/go/
    src/
        hello/          // main
            hello.go
        talk/           //package
            speak.go
    pkg/
    bin/
    README
    LICENSE
  • src目录存放go源代码,目录下可以有若干个源码包,其中有一个是main包(main包的名字可以任意,不一定非要叫做main),main包中包含main方法,编译后即为可执行文件;其他包可以被main包通过import关键字引用。

  • pkg目录存放src中package编译后的结果文件,通常是一个.a文件,注意main包的编译结果不会出现在pkg目录中

  • bin目录存放被最终链接而成的可执行文件

  • README文件用于对工程进行说明

  • LICENSE文件用于声明版权

GOPATH

go使用GOPATH这个环境变量来定义workspace的所在。定义了GOPATH后,你就可以在任意目录下执行编译、链接等操作。

设置GOPATH只需修改.bashrc或者.bash_profile文件,添加GOPATH变量,如下:

GOPATH=/Users/peng/workspace/hello:/Users/peng/workspace/test

这样就声明了两个workspace,多个workspace使用:分隔。

go官方的文档中是推荐只使用一个workspace的,所有的go项目都置于同一个workspace,workspace下的各个源码包可以分别被版本工具(如git)管理。摘录官方文档中的说明如下:

  • Go programmers typically keep all their Go code in a single workspace.

  • A workspace contains many version control repositories (managed by Git, for example).

  • Each repository contains one or more packages.

  • Each package consists of one or more Go source files in a single directory.

  • The path to a package's directory determines its import path

将所有的项目放在一个workspace这种方式,有利有弊:好处是简单、易于管理;坏处就是所有包中依赖的第三方包只有一份,由于Go当前还没有官方的根据版本管理第三方依赖的方式,所以如果有一个项目想要升级一个第三方包的版本,则意味着所有项目都要升级这个版本,可能会带来兼容性等问题。

这里有一篇针对这个问题的讨论:Whats a good best practice with Go workspaces?

二. 依赖管理

go中的依赖以包为单位,当需要引用某个包中的数据结构或者方法时,只需import p(p是一个在workspace中的包路径名)即可,然后代码中就可以p.funcA()这样调用p包中的方法了。

通常,包路径名是一个从workspace根目录作为base的相对路径,直到最下一层目录。在一个workspace中,包路径名必须是唯一的。例如有一个包路径为"talk/speak",则我们在代码中默认情况下可以直接使用speak来代指这个包。除此之外,我们还可以给包路径另起别名,例如import s talk/speak,则s可以代指talk/speak这个包。

大型项目通常还会引用很多第三方开源包,go对此也提供了支持:允许直接import来自远程的package,通常是来自github中的开源包。使用过程如下:(以web框架gin为例)

// 当配置了GOPATH后,在任何目录下执行均可
go get -u github.com/gin-gonic/gin

此时会发现,GOPATH目录下的src目录下已经多了一个github.com目录,下面有刚刚获取到的gin相关包。

完成这些之后,我们就可以在代码中import github.com/gin-gonic/gin,来使用gin包中的代码了。

目前看起来一切ok,但是实际生产过程中我们还会遇到如下问题:

  • 如果我们依赖的第三方包代码修改了,变得不再适合我们使用了,该怎么办呢?有没有办法使每个项目单独指定自己依赖的第三方包的版本?

  • 项目中依赖的第三方包很多,难道每个开发成员每次都要一个一个去go get下来吗?有没有工具帮我们管理这些依赖呢?

目前已经有很多工具可以帮助我们来解决它们了,例如golang/dep、govendor、vgo。简单介绍一下golang/dep工具,它将依赖包放在工程目录(注意不是GOPATH目录)下的vendor目录进行管理,使工程支持指定依赖的包版本,而且可以很方便的帮我们管理众多依赖。这里不具体展开,更多详细介绍可以参考官方文档:https://golang.github.io/dep/docs/introduction.html

三. 编译打包

完成代码编写后,接下来就需要编译打包了,不像java项目需要打出jar包或者war包,Go项目打包完成后只有一个二进制可执行文件,第三方依赖都已经链接进去了,可以直接执行,便于部署。

go build

我们可以使用go build命令进行编译,使用方式有两种,一种是:

go build xxx  // xxx是具体的包路径

另一种就是直接cd到具体的包中,执行:

go build

如果go build的是main包,则会在当前目录中生成二进制执行文件,如果是其他包,则在编译后会将编译结果清除掉,因此看起来好像没有发生任何变化,但是可以帮助我们检查代码是否能够编译通过。

go install

go install的使用方式与go build相同,也是指定一个包或者先进入包路径后执行。

对于main包,命令默认会将编译、链接后的可执行文件放到GOBIN系统变量所指的目录下,如果我们没有设置GOBIN环境变量,则默认是放到GOPATH目录下的bin目录下;对于其他包,则会将链接文件“安装”到GOPATH下的pkg目录下。

四. 部署上线

上线的过程其实就是将编译后的可执行文件以及相关配置文件部署到线上服务器的过程。比较简单的方式是可以通过一个部署脚本,将编译后的包拷贝到线上服务器特定目录下,更为灵活的方式则可以通过Docker构建一个包含可执行文件、依赖配置、第三方库等的镜像,保证所有部署实例均为同一环境。后续会单独介绍。

参考资料

  • 许式伟:《Go语言编程》

  • How to Write Go Code

  • stackoverflow:go install always uses GOROOT/bin instead of GOPATH

  • stackoverflow:Whats a good best practice with Go workspaces?

  • stackoverflow:What is the use of pkg directory in Go?

  • stackoverflow:What does go build build?

  • https://github.com/golang/dep

  • https://github.com/golang/vgo

  • https://github.com/kardianos/govendor


以上是关于Go语言学习五——工程管理的主要内容,如果未能解决你的问题,请参考以下文章

golang基础-Postgresql-ORM框架github.com/go-pg/pg学习五(实战)

golang基础-Postgresql-ORM框架github.com/go-pg/pg学习五(实战)

npm : 无法加载文件 D:softcodeProcess ode ode_global pm.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/go.micr +(代码片段

[Go] 并发和并行的区别

GO语言学习系列五——GO的控制语句(补充指针)

GO语言入门第五节 Go语言的并发编程