An interface type specifies a method set called its interface. A variable of interface type can store a value of any type with a method set that is any superset of the interface. Such a type is said to implement the interface. The value of an uninitialized variable of interface type is nil.
接口声明行为
接口名字一般使用er/or结尾的表动作的名词
多态
接口不是类型的一部分
接口一个双字数据结构
一个指针指向type相关的信息结构体 iTable(type info + method set)
一个指针指向数据
不需要显式的声明某一个类型实现了某一个接口
通过方法集弄清楚一个类型是否实现了某接口
接口可以组合composite
尽可能让接口小 (The bigger the interface, the weaker the abstraction - Rob Pike)
funcmain() { var t Tom elemType := reflect.TypeOf(&t).Elem() // Elem returns the value that the interface v contains or that the pointer v points to n := elemType.NumMethod() for i := 0; i < n; i++ { fmt.Println(elemType.Method(i).Name) } // => Color
var pt *Tom elemType = reflect.TypeOf(&pt).Elem() n = elemType.NumMethod() for i := 0; i < n; i++ { fmt.Println(elemType.Method(i).Name) } // => Color, Paint, RemovePaint }
for i := 0; i < len(tasks); i++ { fmt.Println("paint", tasks[i], "to white color") paintIt(tasks[i], "white") fmt.Println("after paint", tasks[i]) } }
// paint &{table black} to white color // after paint &{table black} // paint &{chair red} to white color // after paint &{chair white} // paint &{tv while} to white color // no way to paint this one // after paint &{tv while}
Testing
测试是go的一等公民,所以自带了一个testing的框架
test file 必须以 _test.go 结尾
test 方法命名必须以 Test 开头
test code 和 code 在同一个文件夹
table testing 是 idiomatic, 标准库很多test是这么写的
自带test coverage tool
可以方便的测试http
1 2 3 4 5 6
go test # 在当前folder跑test go test -v # 在当前folder跑test 并打印测试信息 go test .../. # 在当前文件夹以及子文件夹中跑test go test --run hello # 跑含有hello的tests go test -coverprofile=cov.out # 生成测试覆盖结果 go tool cover -html=cov.out # 在网页中测试覆盖结果
for _, u := range testcases { actual, expected := sayNumber(u.value), u.expected if actual != expected { t.Fatalf("Use case %v expected %v but got %v", u.value, expected, actual) } } // => Failed Use case 1 exptected 10 but got 2 }
MicroBenchmarks
go自带有性能测试的支持
Benchmark tests 也放在 _test.go 的文件中
Benchmark 为test的前缀
Test用的是 testing.T 而Benchmark用的是testing.B
测试跑的次数b.N 会自动被调整 确保测量是可靠的
默认的测试时间是1s 但是可以通过-benchtime调整
可以用-benchmeme来检测内存的分配
跑test并不会跑Benchmark
assign 返回值 避免 inlining
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
var Output string
funcBenchmarkGreet(b *testing.B) { // test setup
// reset timer if needed b.ResetTimer()
var output string for i := 0; i < b.N; i++ { // assign return avoid inlining output = greeter.Greet("hi") } Output = output } // go test -bench Greet // go test -bench Greet --benchmem // go test -bench Greet --benchtime 5s