Go语言似乎是个偏执狂,牺牲了不必要的灵活性,带来一些强制的编程风格和约定。比如:
- 无任何形式的Makefile,模块就是目录、包就是目录、编译配制就是目录!
- 不光目录被用上了,文件名还能指定用途。文件名后缀为_test.go的都是单元测试文件,_linux32.go就是32位linux特定的代码。
- 不光文件名被用上了,函数名还有特定用途。在单元测试文件中,测试函数以Test开头。以大写字母开头的变量、类型和函数是外部可见的,小写字母开头的变量、类型和函数是外部不可见的。
类似的约定也不好说是go语言首创,在一些文件格式中也有类似规范。但是我暂时不知道到有什么其它编程语言对编程风格这么带强制性。
对于单元测试,假设有如下calc.go文件:
package calc
func Add(a,b int) int {
return a+b
}
func Max(a,b int) (ret int) {
ret = a
if b > a {
ret = b
}
return
}
func Min(a,b int) (ret int) {
ret = a
if b < a {
ret = b
}
return
}
有如下测试代码calc_test.go:func Add(a,b int) int {
return a+b
}
func Max(a,b int) (ret int) {
ret = a
if b > a {
ret = b
}
return
}
func Min(a,b int) (ret int) {
ret = a
if b < a {
ret = b
}
return
}
package calc
import (
"testing"
)
type calcTest struct {
a,b,ret int
}
var addTests = []calcTest{
calcTest{4,6,10},
calcTest{5,6,11},
calcTest{8,-10,-2},
}
func TestAdd(t *testing.T) {
for _,v := range addTests {
ret := Add(v.a,v.b)
if ret != v.ret {
t.Errorf("%d add %d,want %d,but get %d",v.a,v.b,v.ret,ret)
}
}
}
func TestMax(t *testing.T){
a,b := 100,300
ret := Max(a,b)
if ret != b {
t.Errorf("%d is bigger than %d",b,a)
}
}
func TestMin(t *testing.T) {
a,b := 100,300
ret := Min(a,b)
if ret != a {
t.Errorf("%d is smaller than %d",a,b)
}
}
执行go test 得到如下结果:import (
"testing"
)
type calcTest struct {
a,b,ret int
}
var addTests = []calcTest{
calcTest{4,6,10},
calcTest{5,6,11},
calcTest{8,-10,-2},
}
func TestAdd(t *testing.T) {
for _,v := range addTests {
ret := Add(v.a,v.b)
if ret != v.ret {
t.Errorf("%d add %d,want %d,but get %d",v.a,v.b,v.ret,ret)
}
}
}
func TestMax(t *testing.T){
a,b := 100,300
ret := Max(a,b)
if ret != b {
t.Errorf("%d is bigger than %d",b,a)
}
}
func TestMin(t *testing.T) {
a,b := 100,300
ret := Min(a,b)
if ret != a {
t.Errorf("%d is smaller than %d",a,b)
}
}
PASS
ok _/home/liangdi/Desktop/test/go/testing 0.008
在calc.go中设计一个逻辑错误,把 func Min(a,b int) ret int 改为:ok _/home/liangdi/Desktop/test/go/testing 0.008
func Min(a,b int) (ret int) {
ret = a
//逻辑错误
if b > a {
ret = b
}
return
}
执行go test的结果为:ret = a
//逻辑错误
if b > a {
ret = b
}
return
}
--- FAIL: TestMin (0.00 seconds)
calc_test.go:38: 100 is smaller than 300
FAIL
exit status 1
FAIL _/home/liangdi/Desktop/test/go/testing 0.005s
calc_test.go:38: 100 is smaller than 300
FAIL
exit status 1
FAIL _/home/liangdi/Desktop/test/go/testing 0.005s