go基础第一篇:defer、select、range

defer

defer用于延迟函数的调用,每次defer都会把一个函数压入栈中,函数返回前再把延迟函数取出并执行。

题目1:

func main() {
    test1()
}

func test1() {
    var aInt = 1

    defer fmt.Println(aInt)

    aInt = 2
    return
}

会打印1。

延迟函数的参数在defer语句出现时就已经确定了,后面不管如何修改aInt变量都不会影响延迟函数。

题目2:

func main() {
    test2()
}

func test2() {
    var aInt = 1

    defer func(i int) {
        fmt.Println(i)
    }(aInt)

    aInt = 2
    return
}

会打印1。

延迟函数的参数在defer语句出现时就已经确定了。此处的延迟函数是个匿名函数,该匿名函数的入参在defer出现时就赋值了。

题目3:

func main() {
    test3()
}

func test3() {
    var aInt = 1

    defer func() {
        fmt.Println(aInt)
    }()

    aInt = 2
    return
}

会打印2。

延迟函数的参数在defer语句出现时就已经确定了。此处的延迟函数是个闭包(在匿名函数里用到了外部变量,就是所谓的闭包),闭包只有在真正执行时,才会去读外部变量的值。

题目4:

func printArray(array [3]int) {
    for i := range array {
        fmt.Println(array[i])
    }
}

func printArrayPointer(array *[3]int) {
    for i := range array {
        fmt.Println(array[i])
    }
}

func test4() {
    var aArray = [3]int{1, 2, 3}
    defer printArray(aArray)
    defer printArrayPointer(&aArray)
    aArray[0] = 10
}

func main() {
    test4()
}

会打印10、2、3、1、2、3。

延迟函数的参数在defer语句出现时就已经确定了。如果是值类型(如数组),会发生拷贝,因此后续修改不会影响 defer 执行时的结果;如果是指针类型,虽然指针本身在defer时确定,但它指向的数据可能被修改,因此defer执行时看到的是最新数据。

题目5:

func test5() (result int) {
    i := 1

    defer func() {
        result++
    }()

    return i
}

func main() {
    a := test5()
    fmt.Println(a)
}

会打印2。

return后面跟变量时,return语句不是原子的,如果函数是具名返回值函数,则会先把return关键字后面的变量赋值给具名返回值变量,然后再执行defer函数,最终返回该具名返回值变量的值。

即test5函数的实际执行过程是

i := 1

result := i

result++

最后返回result的值。

题目6:

func main() {
    a := test6()
    fmt.Println(a)
}

func test6() int {
    var i int

    defer func() {
        i++
    }()

    return i
}

会打印0。

return后面跟变量时,return语句不是原子的,如果函数是匿名返回值函数,则会先把return关键字后面的变量赋值给一个临时变量,然后再执行defer函数,最终返回该临时变量的值。

即foo函数的实际执行过程是

tmp := i

i++

最终返回tmp变量的值。

select

select块中,除default外,每个case都操作一个channel,要么读,要么写。如果所有case都阻塞,那么会执行default语句,如果没有default语句,那么select块会阻塞。空select块会阻塞。

 

posted on 2020-05-22 18:16  koushr  阅读(451)  评论(0)    收藏  举报

导航