6.3. 新建一个包

根据一般约定,导入路径为x/y的包的源代码应放在$GOROOT/src/pkg/x/y目录中。

6.3.1. Makefile

如果能有专门针对Go的工具能检测源代码文件,决定编译顺序就好了,但现在,我们还只能用GNU的make。所以,新建包首先要新建的文件就是Makefile。如果是在Go源代码树中,其基本格式可参照src/pkg/container/vector/Makefile:

  include ../../../Make.inc
  TARG=container/vector
  GOFILES=      intvector.go      stringvector.go      vector.go  include ../../../Make.pkg

在Go的源代码树之外(个人包),标准的格式则是:

  include $(GOROOT)/src/Make.inc
  TARG=mypackage
  GOFILES=      my1.go      my2.go  include $(GOROOT)/src/Make.pkg

第一行和最后一行分别导入了标准定义和规则。Go源代码树中所维护的包使用相对路径(代替$(GOROOT)/src),所以即使是$(GOROOT) 中含有空格也可以正常使用。这无疑简化了程序员尝试Go的难度。

如果没有设置$GOROOT环境变量,在运行gomake时就必须使用第二种makefile。即使系统中的GNU Make的名字是gmake而不是make,Gomake也能正常的调用它。

TARG 是这个包的目标安装路径,就是客户用来导入这个包的字符串。在Go的源代码树种,这个字符串必须跟Makefile中的目录保持一致,不需 要$GOROOT/src/pkg/前缀。在Go的源代码树之外,则可以使用任何跟标准Go包名称不冲突的TARG。一个常见的规则是用一个独有的名称把 自己的包组合在一起,例如:myname/tree、 myname/filter等。注意,即使包的源代码是放在Go源代码树外部,为了便于编译器找到你的包,运行make install之后最好也把编译后的包放到标准位置,即$GOROOT/pkg。

GOFILES是创建包所需要编译的源代码文件清单。用反斜杠符号\就能将这份清单分成多行,方便排序。

如果在Go的源代码树中新建包目录,只需要将其添加到$GOROOT/src/pkg/Makefile的清单中,就能将其包含在标准构建中。然后运行:

  cd $GOROOT/src/pkg
  ./deps.bash

这是更新依赖文件Make.deps。(每次运行all.bash或make.bash时都会自动执行此操作。)

如果是修改一个已有的包,就不需要编辑$GOROOT/src/pkg/Makefile,不过运行deps.bash还是必须的。

6.3.2. Go源文件

对于每个源代码文件,在Makefile中的命令首先是包的名称,该名称也是导入包的默认名称。(同一个包中所有文件必须使用同一个名称。)Go的规则是, 包的名称是导入路径的最后一个元素,例如以“crypto/rot13”为导入路径的包的名称应该是rot13。现在,Go工具还要求链接到同一个二进制 文件的所有包的名称都应该是唯一的,但这个限制很快就会被移除。

Go会一次性编译包中所有的源代码文件,所以源代码中可以试用其它文件中的常量、变量、类型和函数,而无需特别的安排或声明。

编写简洁易懂的Go代码超出了本文档的范围。Effective Go对此有介绍。