Go 学习笔记(五)- 函数

函数在任何语言里都是非常重要的角色,特别是 go 或 js ,函数作为一等公民的存在,我们必须把它嚼烂。

函数声明

1
2
3
func name(参数列表) (返回值列表) {
函数体
}

go 的函数以 func 声明,我感觉除了多了参数类型和返回值类型,其他都跟 js 差不多,因为 go 也有匿名函数,也可以把函数赋值给其他变量,非常方便。

1
2
func add(x int, y int) int {return x + y}
func add(x, y int) int {return x + y}

如果参数类型一致,可以合并声明。

递归

感觉都差不多,略。。

多返回值

这是我第一次接触函数返回多值的情况,非常有意思。

1
2
3
4
5
func test(a, b int) (int, int) {
a++
b++
return a, b
}

一般 go 会在第二个参数当做错误值返回。

错误

这里主要就是第二个参数的应用,系统里N多包都会返回两个参数,第二个是错误参数,方便判断。

1
2
3
4
resp, err := http.Get(url)
if err != nil{
return nill, err
}

函数值

在Go中,函数被看作第一类值(first-class values), 用 js 的术语来说,就是函数表达式。

1
2
3
4
5
test := func(a, b int) (int, int) {
a++
b++
return a, b
}

跟 js 不一样的是,当直接赋值时,函数名不能写。
而定义函数类型的变量时,写法需要注意,而且函数类型变量的零值是 nil

1
var f func(int) int

匿名函数

感觉把 js 函数概念拆开来了。。
这里的匿名函数,就是一个没有函数名的函数字面量,这里就不多记录了,反正 jser 都懂的。

可变参数

在参数名后面加 ... 可以把多余参数当做数组保存在这个变量中。
跟 es6 的特性差不多,不过 es6 的是在参数名前。

1
2
3
4
5
6
7
func sum(vals...int) int {
total := 0
for _, val := range vals {
total += val
}
return total
}

调用的时候可以传入多参或者通过切片类型解构调用。

1
2
3
values := []int{1, 2, 3, 4}
fmt.Println(sum(1, 2, 3, 4)) // "10"
fmt.Println(sum(values...)) // "10"

Deferred 函数

通过在某个语句前加 defer 关键字,让该语句在函数 return 后执行。
多语句的情况下可以提供匿名函数处理。

Panic异常 与 Recover捕获异常

1
2
3
4
5
6
7
8
func Parse(input string) (s *Syntax, err error) {
defer func() {
if p := recover(); p != nil {
err = fmt.Errorf("internal error: %v", p)
}
}()
// ...parser...
}

目前我的理解只是通过 deferrecover 来处理函数内部运行时的异常。

小结

函数部分整体来说跟 es6 有着不少类似之处,语法层面的理解还是比较容易的。
更深层次的理解,需要在之后实际应用中体会了。