Golang内置了单元测试的库testing,利用该库可以进行单元测试。
对于一个可被testing库测试的源文件有两点要求:
test结尾,比如hello_test.goTest开头,函数参数必须是t *testing.T, 比如func TestHello(t *testing.T){},如下是要被测试的代码:
// hello_test.go
package hello_test
import "testing"
func TestHello(t *testing.T) {
	t.Log("hello")
}
然后输入
go test 包名 -v 函数名,
比如:
go test hello_test -v TestHello
就会执行想要测试的函数,对于上述的hello_test.go,在控制台会输出下面结果:

图中画红线的部分就是代码中输出语句的结果。
题目:
求数组中的子数组中和最大的子数组。
比如数组[-3, -4, 5, -3, -1]最大子数组是[5]。
比如数组[-3, 5, -1, 6, -4]最大子数组是[5, -1, 6].
分析:
对于这道题,求子数组,那么就是原数组中连续的若干个元素组成的数组,第一反应想到双指针解法,虽然不是最优的。
对于双指针解法,代码如下:
// max_subarray_test.go
package max_subarray_test
import "testing"
// 数组求和函数
func sum(nums []int) int {
	sum := 0
	for _, num := range nums {
		sum += num
	}
	return sum
}
// 求一个数组的最大子数组
// 本方案时间复杂度O(N^2)
func maxSubArr(arr []int) (int, []int) {
	inputArr := arr
	maxSubArr := inputArr[:]
	leftIndex := 0
	rightIndex := len(inputArr) - 1
	max := inputArr[0]
	// 双指针法,从两侧向中间逼近
	for leftIndex <= rightIndex {
		// 如果在某个范围,子数组的和比最大值大,那么保存当前子数组和最大值
		temp := sum(inputArr[leftIndex : rightIndex+1])
		if temp > max {
			max = temp
			maxSubArr = inputArr[leftIndex : rightIndex+1]
		}
		// 如果该子数组只剩下一个元素了,直接返回
		if len(maxSubArr) <= 1 {
			break
		}
		// 继续向中间逼近,看左边和右边的数哪个数小,小的向中间走
		if inputArr[leftIndex] < inputArr[rightIndex] {
			leftIndex++
		} else {
			rightIndex--
		}
	}
	return max, maxSubArr
}
func TestMaxSubArray(t *testing.T) {
	inputArr := []int{-2, -3, -5, -1, -9}
	max, subArr := maxSubArr(inputArr)
	t.Logf("输入的数组:%v,最大子数组:%v,最大值:%v", inputArr, max, subArr)
	inputArr = []int{-2, 4, -3, 6, -9}
	max, subArr = maxSubArr(inputArr)
	t.Logf("输入的数组:%v,最大子数组:%v,最大值:%v", inputArr, max, subArr)
}
输入命令:
go test max_subarray_test.go -v TestMaxSubArray
显示如下结果:

Golang自带了性能分析工具pprof,可以记录在程序运行过程中CPU和内存的使用情况。
这里就测试上述的“求数组中最大子数组”的代码,测试如下:
// max_subarray.go
package main
import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime"
	"runtime/pprof"
)
// 数组求和函数
func sum(nums []int) int {
	sum := 0
	for _, num := range nums {
		sum += num
	}
	return sum
}
// 求一个数组的最大子数组
// 本方案时间复杂度O(N^2)
func maxSubArr(arr []int) (int, []int) {
	inputArr := arr
	maxSubArr := inputArr[:]
	leftIndex := 0
	rightIndex := len(inputArr) - 1
	max := inputArr[0]
	// 双指针法,从两侧向中间逼近
	for leftIndex <= rightIndex {
		// 如果在某个范围,子数组的和比最大值大,那么保存当前子数组和最大值
		temp := sum(inputArr[leftIndex : rightIndex+1])
		if temp > max {
			max = temp
			maxSubArr = inputArr[leftIndex : rightIndex+1]
		}
		// 如果该子数组只剩下一个元素了,直接返回
		if len(maxSubArr) <= 1 {
			break
		}
		// 继续向中间逼近,看左边和右边的数哪个数小,小的向中间走
		if inputArr[leftIndex] < inputArr[rightIndex] {
			leftIndex++
		} else {
			rightIndex--
		}
	}
	return max, maxSubArr
}
func contentTesting() {
	for i := 0; i < 10000; i++ {
		inputArr := []int{-2, -3, -5, -1, -9}
		max, subArr := maxSubArr(inputArr)
		fmt.Printf("输入的数组:%v,最大子数组:%v,最大值:%v\n", inputArr, max, subArr)
	}
}
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to `file`")
var memprofile = flag.String("memprofile", "", "write memory profile to `file`")
func main() {
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal("could not create CPU profile: ", err)
		}
		defer f.Close() // error handling omitted for example
		if err := pprof.StartCPUProfile(f); err != nil {
			log.Fatal("could not start CPU profile: ", err)
		}
		defer pprof.StopCPUProfile()
		contentTesting()
	}
	contentTesting()
	if *memprofile != "" {
		f, err := os.Create(*memprofile)
		if err != nil {
			log.Fatal("could not create memory profile: ", err)
		}
		defer f.Close() // error handling omitted for example
		runtime.GC()    // get up-to-date statistics
		if err := pprof.WriteHeapProfile(f); err != nil {
			log.Fatal("could not write memory profile: ", err)
		}
		contentTesting()
	}
}
然后编译上述源文件:
go build max_subarray.go
会生成可执行文件max_subarray,然后执行该可执行文件,输入参数,表示输出cpu信息:
./max_subarray --cpuprofile=cpu.pprof
此时会生成名称为cpu.pprof的二进制文件,无法直接打开,需要使用golang的too工具下的pprof打开它:
go tool pprof cpu.pprof
可以看到CPU在程序执行过程中的信息:

也可以以生成函数调用图,如下:
go tool pprof -svg ./cpu.pprof

原文:https://www.cnblogs.com/TheFxxkingPython/p/14524467.html