smallfish bio photo

smallfish

Engineer at Alibaba, Taobao.com #golang #clojure #nginx-lua #postgres

Email Twitter Github

原文:http://golang.org/doc/code.html

简述

这篇文档描述了如何去写一个新的 package 和怎么去测试。本文假设你已经按照http://golang.org/doc/install.html装好Go。

在修改一个存在的 package 或者新建立一个package,确保先发一封邮件到 http://groups.google.com/group/golang-nuts,告诉大家你想做什么。这样有助于不要重复造轮子,在写代码之前最好讨论下。

社区资源

如果想获取实时帮助,可以加入 http://freenode.net/ 上 IRC 频道 #go-nuts。

Go 语言官方邮件列表是 http://groups.google.com/group/golang-nuts.

Bugs 可以参考http://code.google.com/p/go/issues/list.

对于那些想尝试开发代码的用户,这里有另外一个邮件列表 http://groups.google.com/group/golang-checkins,邮件里包含了那些刚提交到 Go 代码库的消息。

建立Go包

下面的源码假设 package 的导入路径是 x/y,约定下保存的路径是:$GOROOT/src/pkg/x/y

Makefile

这将是很好的利用 Go-specific 工具里安排源码结构,如何按照顺序和构建代码。Go 使用 GUN make。所以首先在一个新的package 文件夹里建立一个 Makefile。最简单的做法就是从 http://golang.org/src/pkg/container/vector/Makefile 源码包里拷贝一份。

include ../../../Make.$(GOARCH)

TARG=container/vector
GOFILES=\
	intvector.go\
	stringvector.go\
	vector.go\

include ../../../Make.pkg

当然在上面的源码包之外写一个新的 package ,通常的 Makefile 如下:

include $(GOROOT)/src/Make.$(GOARCH)

TARG=mypackage
GOFILES=\
	my1.go\
	my2.go\

include $(GOROOT)/src/Make.pkg

第一行 include 标准的定义和规则,package 的路径一般相对路径来代替 $(GOROOT)/src ,这样做到目的就是防止 make 时候 $(GOROOT) 含有空格,这样做很方便开发中使用Go。

TRAG 是包安装路径,这行就是其他程序导入到名字。在 Go 源码中,这个名字必须和文件夹中的 Makefile 中的一致,不需要 $GOROOT/src/pkg/ 前缀。在源码之外,你可以任意起名而不要和标准 package 的重名即可。常见的做法是独立一个 package 名:myname/tree, myname/filter,确保你的代码在 myname 里,运行 make install,将会编译后把二进制文件放入 $GOROOT/pkg,可以很方便的找到。

GOFILES 放入文件内需要编译的源码列表。多行用 \ 字符隔开。

如果想在 Go 源码树中新建包,需要添加列表到 $GOROOT/src/pkg/Makefile 中作为标准库编译,编译运行:

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

更新依赖文件 Make.deps (这是每次 make all 或者 make build 都需要)

Go 源文件

在每个源码里第一行的名字应该是 Makefile 里面定义的 package 名,这里的 name 是作为默认的名字导入。(包里的每个 package 名都应该是同样的名字)Go的惯例是用路径的最后一个元素作为名字,比如 “crypto/rot13” 应该是 rot13。到目前为止,Go 是依靠 package 名字来确定一个二进制的文件,当然可能会很快的取消。

Go 是在一个包内编译源码文件,在一个文件定义常量,变量,类型或者函数,在其他文件内适用不需要再定义和声明。

想写一个干净而优美的 Go 代码不在本文范围。请参考http://golang.org/doc/effective_go.html吧。

测试

Go 有一个轻量级的测试代码框架:gotest。编写一个测试代码,只需要新建一个跟你源码名字一样,加上:_test.go 即可,测试函数一般是 func TestXXX (t *testing.T)。每次运行测试其中的函数。如果想返回错误的话一般是返回: t.Error 或 t.Fail,测试时候就会抛错。详细 gotest 测试方法请参考:http://golang.org/cmd/gotest/

*_test.go 不需要在 Makefile 中声明。

运行测试,编译时候 make test 即可,和 gotest 效果一样。如果想单独测试某一个源码,比如:one_test.go,则运行:gotest one_test.go。

如果你的修改影响性能,可以添加一个性能测试函数(参考:http://golang.org/cmd/gotest/),然后运行:gotest -benchmarks=.

当你新的代码已经通过测试,也能运行,你就可以 review 和 commit.  http://golang.org/doc/contribute.html

一个测试的例子

这是一个名字叫 numbers 测试 package ,定义了一个叫 Double 的函数,返回一个整型,结果是输入的参数乘以2。一共有三个文件。

第一个是 numbers.go

package numbers

func Double(i int) int {
	return i * 2
}

第二个是测试文件 numbers_test.go

package numbers

import (
	"testing"
)

type doubleTest struct {
	in, out int
}

var doubleTests = []doubleTest{
	doubleTest{1, 2},
	doubleTest{2, 4},
	doubleTest{-5, -10},
}

func TestDouble(t *testing.T) {
	for _, dt := range doubleTests {
		v := Double(dt.in)
		if v != dt.out {
			t.Errorf("Double(%d) = %d, want %d.", dt.in, v, dt.out)
		}
	}
}

最后是 Makefile 文件

include $(GOROOT)/src/Make.$(GOARCH)

TARG=numbers
GOFILES=\
	numbers.go\

include $(GOROOT)/src/Make.

运行 make install 将会构建和安装包到 GOROOT/pkg/ 文件夹内(他在系统的任何地方导入调用)。

运行 make test (或者 gotest)将会重新构建包,并会运行 numbers_test.go 中的 TestDouble 函数。如果输出 “PASS” 则表示测试成功通过。如果不是2到3的倍数,将会看到错误报告。

更详细的请查看http://golang.org/cmd/gotest/文档。