函数(知乎)学习笔记
函数知乎系列笔记
1. 多返回值函数
// 定义sum函数
func sum(a, b int) (int, error) {
if a < 0 || b < 0 {
return 0, errors.New("a或b不能是负数")
}
return a + b, nil
}
func main() {
// 调用sum函数,并且定义两个变量接收函数返回值
res, err := sum(-1, 9)
if err != nil {
fmt.Println(res, err)
} else {
fmt.Println(res)
}
}
out
0 a或b不能是负数
- 第一个知识点,函数的多值返回,返回值有两个,一个是int类型,一个是error类型。这是Go里面典型的多值返回,在Go中,很多都是多值返回,一个返回正常值,另外一个返回的是error信息。在实际编程中,非常常见。
- 第二个知识点,很重要,是自定义error。我们利用
errors.New()
自定义了一个error,当有一个为负数时就退出程序并且抛出异常信息。 - 如果不想接收error信息,可以使用哑元变量接收。
res, _ := sum(-1, 9)
2. 函数返回值可以命名
函数返回值也可以有变量名称,同样的,返回值名称在前,类型在后
。程序示例:
func sum(a, b int) (sum int, err error) {
if a < 0 || b < 0 {
return 0, errors.New("a或b不能是负数")
}
sum = a + b
err = nil
return // 后面省略了,这种写法后面编码中会经常用的,使用了命名方式的返回值,这里是可以省略的
}
func main() {
res, err := sum(-1, 9)
if err != nil {
fmt.Println(res, err)
} else {
fmt.Println(res)
}
res, err = sum(1, 3)
if err != nil {
fmt.Println(res, err)
} else {
fmt.Println(res)
}
}
这个程序也很经典,值得学习:
- 对返回值命名了,并且最后的return省略返回值,如果没有命名,这个是不能省略的。
- 在main函数中,调用了两次,第一次是异常调用,会输出异常信息,第二次是正常调用,正常输出返回值。在学习过程中,我第二次调用没有进行捕获异常和打印输出,以为程序在第一次抛出异常后就退出了,还在技术群傻傻的问,如何让第一次异常后,让第二次正常调用, 本来就可以正常调用的,只是我没有输出而已。
return
只是上面函数走完了,mian函数
还在继续往下走的。 - 主程序中使用
if !err
进行判断,这是极为常见的写法。
3. 可变参数
func sum1(params ...int) int {
sum := 0
for _, i := range params {
sum += i
}
return sum
}
func main() {
fmt.Println(sum1(1, 2))
fmt.Println(sum1(1, 2, 3))
}
注意点
可变参数的类型是切片
!这个例子比B站老男孩里讲的好!- 不管函数有多少个参数,可变参数一定要放在最末尾。
4. 函数可见性
- 函数名称首字母
小写
代表私有函数,只有在同一个包
中才可以被调用 - 函数名称首字母
大写
代表共有函数,不同的包
也可以调用 - 任何一个函数都会从属一个包
5. 匿名函数和闭包
func main() {
sum1 := func(a, b int) int {
return a + b
}
fmt.Println(sum1(1, 2))
}
没有名称的函数叫匿名函数,需要注意的是,sum1是函数类型的变量!
在函数中再定义函数,可以使用外部函数的变量,这种方式就是闭包
函数类型变量,函数类型的参数,或者作为另外一个函数返回值类型
func colsure() func() int {
i := 0
return func() int {
i++
return i
}
}
func main() {
cl := colsure()
fmt.Println(cl())
fmt.Println(cl())
fmt.Println(cl())
}
要注意这种写法,func() 指的是外部函数的返回值是函数类型,int指的是func()这个函数的返回值是int类型,不要弄混了,也可以这样一起理解 func() int
,返回是一个返回值是int类型的函数,有一点点绕。