GO学习笔记(7)

七. 函数

  GO语言的函数特点:

  1. 不需要声明原型

  2. 支持可变参数

  3. 支持多返回值

  4. 支持匿名函数和闭包

  5. 不支持嵌套

  6. 一个包不能有同名函数

  7. 不支持重载

  8. 不支持默认参数

 

这里重点记录可变参,闭包和延迟调用

  7.1. 可变参

// 固定类型的不定参数
func func1(arg ...int) {
    fmt.Println(arg)
}

// 任意类型的不定参数
func func2(arg ...interface{}) {
    fmt.Println(arg)
}

func main() {
    func1(1, 2, 3)
    a := []int{1, 2, 3, 4}
    func1(a...) // 必须展开
    //func1("qwe") // 报错: cannot use "qwe" (type untyped string) as type int in argument to func1
    func2(1, 2)
    func2(a)    // [[1 2 3 4]]
    func2("qwe")
}

  7.2. 闭包 (和nodejs闭包类似)

func closure() func() {
    i := 0
    x := func() {
        i++
        fmt.Println(i)
    }
    return x
}

func main() {
    a := closure()
    a()        // 1
    a()        // 2
    a()        // 3
    a()        // 4

    closure() // 没有输出
}

  7.3 延迟调用

// 1. 基本用法
func deferDemo() {
// 关键字 defer a := [5]int{} for i := range a{ fmt.Println("i = ", i) defer fmt.Println("defer i = ",i) } for i := range a { defer func() {fmt.Println("closure i = ",i)}() } /** 输出: i = 0 i = 1 i = 2 i = 3 i = 4 closure i = 4 closure i = 4 closure i = 4 closure i = 4 closure i = 4 defer i = 4 defer i = 3 defer i = 2 defer i = 1 defer i = 0 第一次循环里 就使用了defer延迟, 所以最先输出的是 i=xxx; 多个defer语句,按先进后出的方式执行, defer的调用顺序是 defer i=0,1,2,3,4,closure i = 4, 所以先输出closure i = 4 因为第二个循环里使用了闭包, 由于闭包中的i在执行的时候已经是4, 所以输出全部是4 */ } // 2. 易错点 type Test struct { name string } func (t *Test)close1() { //fmt.Println("close1:",t.name) fmt.Printf("close1: %p, %v \n", &t, t.name) } func (t Test)close2() { fmt.Printf("close2: %p, %v \n", &t, t.name) //fmt.Println("close2:", t.name) } func deferDemo2() { ts := []Test{{"a"}, {"b"}, {"c"}} for _, t := range ts { fmt.Printf("deferDemo2:close1: %p \n",&t) defer t.close1() // 传递的是引用类型 } for _, t := range ts { fmt.Printf("deferDemo2:close2: %v \n",t) defer t.close2() // 传递值类型 } /** deferDemo2:close1: 0xc000088230 deferDemo2:close1: 0xc000088230 deferDemo2:close1: 0xc000088230 deferDemo2:close2: {a} deferDemo2:close2: {b} deferDemo2:close2: {c} close2: 0xc000088270, c close2: 0xc000088290, b close2: 0xc0000882b0, a close1: 0xc0000cc020, c close1: 0xc0000cc028, c close1: 0xc0000cc030, c defer后面的语句在执行的时候,函数调用的参数会被保存起来,但是不执行。也就是复制了一份。 close1因为参数是是t的地址, 虽然是复制了三次,但是t的地址是相同的 */ }

// 3. 延迟调用发生错误, 这些调用依然会执行
func deferDemo3(x int) {
defer fmt.Println("a")
defer fmt.Println("b")

defer func() {
fmt.Println(100 / x) // 参数为0, 发生异常
}()

defer fmt.Println("c")
}
func main() {
deferDemo3(1) // c 100 b a
deferDemo3(0) // c b a panic: runtime error: integer divide by zero
}
 

 

你可能感兴趣的:(GO学习笔记(7))