golangのcallbackとdeferの実行順序と表示される値について

[wip][golang]golangのcallbackとdeferの実行順序と表示される値について

はじめに

以下のものを使った際の実行順序を調べたい。

  • defer
  • callback
  • closure(ついで)

テキトウなコード

テキトウなコードを書いて調べる。 10. 20. 30 という数値を持ったslicesの各要素に対して処理をする記述を書くがそれがどのような実行結果になるか調べる。

package main

import (
    "fmt"
)

func main() {
    xs := []int{10, 20, 30}
    callbacks := [](func()){}
    closures := [](func()){}
    for _, x := range xs {
        y := x // block has scope.

        defer fmt.Printf("defer: %d\n", x)
        callbacks = append(callbacks, func() {
            fmt.Printf("callback: %d\n", x)
        })
        closures = append(closures, func() {
            fmt.Printf("closure: %d\n", y)
        })
    }

    for _, cb := range callbacks {
        cb()
    }

    for _, cb := range closures {
        cb()
    }
}

実行結果

実行結果は以下の様になる。 callback, closureは想定通り。deferが想定外。ループ後の変数を参照しているわけではなくdeferを評価したタイミングで何らかの環境的な情報を持っているらしい?

実行順序は、callbackの方がFIFO, deferはLIFOっぽい。

callback: 30
callback: 30
callback: 30
closure: 10
closure: 20
closure: 30
defer: 30
defer: 20
defer: 10

(後で詳しく書く。たぶん。)