5.函数
- 函数声明
- 递归
- 多返回值
- 错误
- 函数值
- 匿名函数
- 可变参数
- Deferred函数
- Panic异常
- Recover捕获异常
函数声明
func name(parameter-list) (result-list) {
body
}
//result-list中可以声明返回值,这样这个返回值会先被初始化。最后函数只要return就可以自动返回result-list的值。
递归:go的递归与其他语言一样
下面是我自己写的一个递归的小程序,求阶乘
package main
import "fmt"
func main() {
fmt.Println(Factorial(3))
}
func Factorial(start int) int {
if start > 1 {
return Factorial(start-1) * start
} else {
return 1
}
}
特别注意原文中这样一句话:
Go语言使用可变栈,栈的大小按需增加(初始时很小)。这使得我们使用递归时不必考虑溢出和安全问题。
多返回值:
参数、返回值的命名最好是有意义的,这样能让我们在阅读代码的时候能够更快的知道意思。
如果返回值中某个值不被使用,可以将其分配给blank identifier:links, _ := findLinks(url)
,这个下划线就相当于我接收了这个值,然会就不管了。
错误:错误不是异常,错误是我们在编程中可以预料的并且在程序中需要显示处理的。Go使用控制流机制(如if和return)处理异常,这使得编码人员能更多的关注错误处理。
错误处理策略:
- 向上传播错误
- 重试(防止无限重试)
- 输出错误信息并结束程序(这个方法只在main函数中执行)。
- 有时,我们只需要输出错误信息就足够了,不需要中断程序的运行。我们可以通过log包提供函数
- 我们可以直接忽略掉错误。
匿名函数
拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(function literal),我们可绕过这一限制,在任何表达式中表示一个函数值。
可变参数
在声明可变参数函数时,需要在参数列表的最后一个参数类型之前加上省略符号“…”,这表示该函数会接收任意数量的该类型参数。
func sum(vals...int) int {
total := 0
for _, val := range vals {
total += val
}
return total
}
values := []int{1, 2, 3, 4}
fmt.Println(sum(values...)) // "10"
Deferred函数
只需要在调用普通函数或方法前加上关键字defer,就完成了defer所需要的语法。当defer语句被执行时,跟在defer后面的函数会被延迟执行。直到包含该defer语句的函数执行完毕时,defer后的函数才会被执行,不论包含defer语句的函数是通过return正常结束,还是由于panic导致的异常结束。你可以在一个函数中执行多条defer语句,它们的执行顺序与声明顺序相反。
func title(url string) error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
ct := resp.Header.Get("Content-Type")
if ct != "text/html" && !strings.HasPrefix(ct,"text/html;") {
return fmt.Errorf("%s has type %s, not text/html",url, ct)
}
doc, err := html.Parse(resp.Body)
if err != nil {
return fmt.Errorf("parsing %s as HTML: %v", url,err)
}
// ...print doc's title element…
return nil
}
Panic异常
Recover捕获异常