Runner in the High

技術のことをかくこころみ

deferで参照している変数のポインタを更新しても参照は変わらないっぽい

こういうやつ

type Closer struct{
    Value string
}

func (c *Closer) Close(id string) {
    fmt.Printf("Closed(%s): %p\n", id, c)
}

func newCloser(c *Closer) {
    n := &Closer{Value: "aaa"}
    fmt.Printf("New: %p\n", n)
    c = n
}

func main() {
    c := &Closer{Value: "bbb"}
    fmt.Printf("Main: %p\n", c)
    defer c.Close("main") // <-- ここのcはnewCloserで作られたCloserのポインタになっているはず...?
    newCloser(c)
}

上記を実行するとこうなる

Main: 0xc000010240
New: 0xc000010250
Closed(main): 0xc000010240

newCloser関数の内部で参照渡しとしてリソースを上書きしたとしてもmainの中のdefer節で呼ばれるCloseメソッドの呼び出し対象の変数cの参照は古いままなので、newCloser関数の中で作られた方のリソースのクローズ漏れが起きる可能性がある。

これを防ぐためにはnewCloser関数のなかでもdeferでリソースのクローズをするしかない。