はじめに
Go言語を最近少しずつ触っている中でdefer
が出てきたのですが、調べただけでは動きがわかりづらかったので触ってみることにしました。この記事は触った記録をメモしたものです。
$ go version
go version go1.18.4 darwin/arm64
deferとは
deferはreturnされるまで実行されない書き方です。
例として以下のコードを考えます。
package main
import "fmt"
func main() {
defer func() {
fmt.Println("defer")
}()
for i := 0; i < 10; i++ {
fmt.Println(i)
}
}
上記のように書いた場合、defer内のfmt.Println("defer")
はfor文の後に実行されます。
$ go run main.go
0
1
2
3
4
5
6
7
8
9
defer
複数のdefer
を定義したときは以下のような挙動をします。
package main
import "fmt"
func main() {
defer func() {
fmt.Println("defer 1")
}()
defer func() {
fmt.Println("defer 2")
}()
defer func() {
fmt.Println("defer 3")
}()
}
いわゆるLIFO(Last In First Out)になっていることがわかります。
$ go run main.go
defer 3
defer 2
defer 1
for文に入れて実行してみると
package main
import "fmt"
func main() {
fmt.Println("counting")
for i := 0; i < 10; i++ {
defer fmt.Println(i)
}
fmt.Println("done")
}
後ろから順番に実行されますね。
$ go run main.go
counting
done
9
8
7
6
5
4
3
2
1
0
さいごに
deferはreturnの直前に実行される関数でした。
用途は、必要なくなったファイルを閉じたり、チャネルを閉じたり、プログラムのパニックをキャッチするために使用されるみたいです。
確かにwebsocketのコードで初めてみたのでなんとなくイメージはあっているのかもしれない。