文章目录
- 目录结构
- 代码示例
- split.go
- split_test.go
- fib.go
- fib_test.go
- 运行结果
- split code
- fib code
目录结构
代码示例
split.go
package split
import "strings"
// 定义一个切割字符串的包
// Split 按照 sep 分割 s, a:b:c --> a b c
func Split(s, sep string) []string {
// 得到字符串中分隔符的数量
sepNum := strings.Count(s, sep)
// 按照分隔符数量申请内存
r := make([]string, 0, sepNum+1)
index := strings.Index(s, sep)
for index >= 0 {
r = append(r, s[:index])
s = s[index+len(sep):]
index = strings.Index(s, sep)
}
r = append(r, s)
return r
}
split_test.go
package split
import (
"fmt"
"os"
"reflect"
"testing"
)
// 子测试集
func TestNormalSplit(t *testing.T) {
get := Split("a:b:c", ":")
want := []string{"a", "b", "c"}
if ok := reflect.DeepEqual(get, want); !ok {
t.Fatalf("期望结果: %v, 实际结果: %v\n", want, get)
}
}
func TestMultiSplit(t *testing.T) {
// 这里是 setup 和 teardown 的使用实例
f := setupT(t)
defer f(t)
get := Split("a::b::c", "::")
want := []string{"a", "b", "c"}
if ok := reflect.DeepEqual(get, want); !ok {
t.Fatalf("期望结果: %v, 实际结果: %v\n", want, get)
} else {
t.Log("pass test...")
}
}
func TestNumSplit(t *testing.T) {
get := Split("1231", "1")
want := []string{"", "23", ""}
if ok := reflect.DeepEqual(get, want); !ok {
t.Fatalf("期望结果: %v, 实际结果: %v\n", want, get)
}
}
// 子测试组
func TestSplitGroup(t *testing.T) {
// 存放测试的结构体
type test struct {
str string
sep string
want []string
}
// 将测试用例都实例化到 map 中
items := map[string]test{
"normal": test{
str: "a:b:c",
sep: ":",
want: []string{"a", "b", "c"},
},
"multi": test{
str: "a::b::c",
sep: "::",
want: []string{"a", "b", "c"},
},
"num": test{
str: "1231",
sep: "1",
want: []string{"", "23", ""},
},
}
for k, i := range items {
t.Run(k, func(t *testing.T) {
get := Split(i.str, i.sep)
if ok := reflect.DeepEqual(i.want, get); !ok {
t.Fatalf("测试关键字: %v, 期望结果: %v, 实际结果: %v\n", k, i.want, get)
}
})
}
}
// 性能测试 - 基础版
func BenchmarkSplit(b *testing.B) {
for i := 0; i < b.N; i++ {
Split("a:b:c", ":")
}
}
// 性能测试 - 并发版
func BenchmarkParallelSplit(b *testing.B) {
// 设置 cpu 数量
// b.SetParallelism(1)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
Split("1231", "1")
}
})
}
// 在全局加前后操作
func TestMain(m *testing.M) {
fmt.Println("start test...")
r := m.Run()
fmt.Println("end test...")
os.Exit(r)
}
// 给单一测试用例加前后操作, 如果是性能测试, t 改 b 即可
func setupT(t *testing.T) func(t *testing.T) {
t.Log("start test...") // 测试前执行
return func(t *testing.T) { // 返回函数名, 使用时 defer 调用
t.Log("end test...")
}
}
fib.go
package fib
// Fib 计算斐波那契数列
func Fib(n int) int {
if n < 2 {
return n
}
return Fib(n-1) + Fib(n-2)
}
fib_test.go
package fib
import "testing"
// 性能测试 - 性能对比, 根据数据量不同进行分析
func benchmarkFib(b *testing.B, n int) {
// 清除耗时
// b.ResetTimer()
for i := 0; i < b.N; i++ {
Fib(n)
}
}
func BenchmarkFib2(b *testing.B) {
benchmarkFib(b, 2)
}
func BenchmarkFib10(b *testing.B) {
benchmarkFib(b, 10)
}
func BenchmarkFib20(b *testing.B) {
benchmarkFib(b, 20)
}
运行结果
split code
xxx@xxx split % go test -v
testMain start test...
=== RUN TestNormalSplit
--- PASS: TestNormalSplit (0.00s)
=== RUN TestMultiSplit
--- PASS: TestMultiSplit (0.00s)
split_test.go:111: setupT start test...
split_test.go:30: pass test...
split_test.go:113: setupT end test...
=== RUN TestNumSplit
--- PASS: TestNumSplit (0.00s)
=== RUN TestSplitGroup
=== RUN TestSplitGroup/normal
=== RUN TestSplitGroup/multi
=== RUN TestSplitGroup/num
--- PASS: TestSplitGroup (0.00s)
--- PASS: TestSplitGroup/normal (0.00s)
--- PASS: TestSplitGroup/multi (0.00s)
--- PASS: TestSplitGroup/num (0.00s)
PASS
testMain end test...
ok xxx/split 0.013s
fib code
xxx@xxx Fib % go test -bench=. -v
goos: darwin
goarch: amd64
pkg: code.oldboy.com/Fib
BenchmarkFib2-4 100000000 10.9 ns/op
BenchmarkFib10-4 2000000 695 ns/op
BenchmarkFib20-4 20000 90912 ns/op
PASS
ok xxx/Fib 5.728s