Go语言圣经(中文版)读书笔记(五)

5.函数

  1. 函数声明
  2. 递归
  3. 多返回值
  4. 错误
  5. 函数值
  6. 匿名函数
  7. 可变参数
  8. Deferred函数
  9. Panic异常
  10. 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)处理异常,这使得编码人员能更多的关注错误处理。

错误处理策略:

  1. 向上传播错误
  2. 重试(防止无限重试)
  3. 输出错误信息并结束程序(这个方法只在main函数中执行)。
  4. 有时,我们只需要输出错误信息就足够了,不需要中断程序的运行。我们可以通过log包提供函数
  5. 我们可以直接忽略掉错误。

匿名函数

拥有函数名的函数只能在包级语法块中被声明,通过函数字面量(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捕获异常

你可能感兴趣的:(Go读书笔记)