go语言笔记—函数
函数是组织好的、可重复使用的、用来实现单一或相关联功能的代码段,其可以提高应用的模块性和代码的重复利用率。Go 语言支持普通函数、匿名函数和闭包,从设计上对函数进行了优化和改进,让函数使用起来更加方便。Go 语言的函数属于“一等公民”(first-class),也就是说:
- 函数本身可以作为值进行传递。
- 支持匿名函数和闭包(closure)。
- 函数可以满足接口。
函数定义
格式:
func 函数名(形式参数列表)(返回值列表){
函数体
}
多返回值:
func typedTwoValues() (int, int) {
return 1, 2
}
对返回值命名:
func namedRetValues() (a, b int) {
a = 3
b = 2
return
}
函数作为变量:
func fire() {
fmt.Println("fire")
}
func main() {
var f func()
f = fire
f()
}
匿名函数:
匿名函数的定义就是没有名字的普通函数定义
定义格式:
func(参数列表)(返回参数列表){
函数体
}
可变参数:
func myfunc(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
}
defer延迟执行语句
Go语言的 defer 语句会将其后面跟随的语句进行延迟处理,在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行。关键字 defer 的用法类似于面向对象编程语言 Java和 c# 的 finally 语句块,它一般用于释放某些已分配的资源,典型的例子就是对一个互斥解锁,或者关闭一个文件。
func main() {
fmt.Println("defer begin")
// 将defer放入延迟调用栈
defer fmt.Println(1)
defer fmt.Println(2)
// 最后一个放入, 位于栈顶, 最先调用
defer fmt.Println(3)
fmt.Println("defer end")
}
递归
斐波拉且:
func Fibonacci(n uint64) (result uint64) {
if n == 1 || n==2 {
return 1
}
return Factorial(n-1) + Factorial(n-2)
}
阶乘:
func Factorial(n int64) (rs int64) {
if n == 1 {
return 1
}
return n*Factorial(n-1)
}
go语言测试
规则:
要开始一个单元测试,需要准备一个 go 源码文件,在命名文件时文件名必须以_test.go
结尾,单元测试源码文件可以由多个测试用例(可以理解为函数)组成,每个测试用例的名称需要以 Test 为前缀,例如:
func TestXxx( t *testing.T ){
//......
}
编写测试用例有以下几点需要注意:
- 测试用例文件不会参与正常源码的编译,不会被包含到可执行文件中;
- 测试用例的文件名必须以
_test.go
结尾; - 需要使用 import 导入 testing 包;
- 测试函数的名称要以
Test
或Benchmark
开头,后面可以跟任意字母组成的字符串,但第一个字母必须大写,例如 TestAbc(),一个测试用例文件中可以包含多个测试函数; - 单元测试则以
(t *testing.T)
作为参数,性能测试以(t *testing.B)
做为参数; - 测试用例文件使用
go test
命令来执行,源码中不需要 main() 函数作为入口,所有以_test.go
结尾的源码文件内以Test
开头的函数都会自动执行。
Go语言的 testing 包提供了三种测试方式,分别是单元(功能)测试、性能(压力)测试和覆盖率测试。
单元测试
在同一文件夹下创建两个Go语言文件,分别命名为 demo.go 和 demt_test.go
demo.go:
// 根据长宽获取面积
func GetArea(weight int, height int) int {
return weight * height
}
demo_test.go:
import "testing"
func TestGetArea(t *testing.T) {
area := GetArea(40, 50)
if area != 2000 {
t.Error("测试失败")
}
}
测试运行:go test -v
压力测试
demo_test.go:
import "testing"
func BenchmarkGetArea(t *testing.B) {
for i := 0; i<t.N; i++{
GetArea(40,50)
}
}
测试运行:go test -bench="."
覆盖率测试
demo_test.go:
import "testing"
func TestGetArea(t *testing.T) {
area := GetArea(40, 50)
if area != 2000 {
t.Error("测试失败")
}
}
func BenchmarkGetArea(t *testing.B) {
for i := 0; i < t.N; i++ {
GetArea(40, 50)
}
}
测试运行:go test -cover