1. 示例一
package main

import "fmt"

type Test struct {
    name string
}

func (t *Test) Close() {
    fmt.Println(t.name, "closed")
}

func main() {
    ts := []Test{{"a"}, {"b"}, {"c"}}
    for _, t := range ts {
        defer t.Close()
    }
}
  • 终端输出
c closed
c closed
c closed
  1. 示例二
package main

import "fmt"

type Test struct {
    name string
}

func (t *Test) Close() {
    fmt.Println(t.name, "closed")
}

func Close(t Test) {
    t.Close()
}

func main() {
    ts := []Test{{"a"}, {"b"}, {"c"}}
    for _, t := range ts {
        defer Close(t)
    }
}
  • 终端输出
c closed
b closed
a closed
  1. 示例三
package main

import "fmt"

type Test struct {
    name string
}

func (t *Test) Close() {
    fmt.Println(t.name, "closed")
}

func main() {
    ts := []Test{{"a"}, {"b"}, {"c"}}
    for _, t := range ts {
        ts := t
        defer ts.Close()
    }
}
  • 终端输出
c closed
b closed
a closed

通过示例一可知: defer后面的语句在执行时,函数调用的参数会被保存起来,但是不执行,也就是被执行了一份。
通过示例二可知: 多个defer注册,按FILO次序执行(先进后出)。如果函数或某个延迟调用发生错误,这些调用依然会被执行。

滥用defer可能导致性能问题

package main

import "fmt"

var lock sync.Mutex

func test() {
    lock.Lock()
    lock.Unlock()
}

func testdefer() {
    lock.Lock()
    defer lock.Unlock()
}

func main() {
    func() {
        t1 := time.Now()
        for i := 0; i < 10000; i++ {
            test()
        }
        elapsed := time.Since(t1)
        fmt.Println("test elapsed:", elapsed)
    }()
    func() {
        t1 := time.Now()
        for i := 0; i < 10000; i++ {
            testdefer()
        }
        elspsed := time.Since(t1)
        fmt.Println("testdefer elapsed:", elspsed)
    }()
}
  • 终端输出
test elapsed: 91.939µs
testdefer elapsed: 117.622µs