2020/03/04

[golang]defer

関数を抜けるときに実行してくれる処理を指定することができるそうだ。

それがdefer。

Defer, Panic, and Recover - The Go Blog
https://blog.golang.org/defer-panic-and-recover

なぜか知らんが、deferとpanicとrecoverは並べて比べるもののようだ。
まあ、後者2つは知らんのだがね。


deferキーワードを付けた関数はリストに載せられ、リストに載ったものは関数がreturnする際に呼び出されるそうだ。リストは上に積んでいくタイプで、呼ばれるときも上から順番だ。

 

src/ex7/main.go

01: package main
02: 
03: import "fmt"
04: 
05: func main() {
06: 	defer fmt.Printf("Yoshio.\n")
07: 	defer fmt.Printf(" is ")
08: 	defer fmt.Printf("My name")
09: }
  

src$ go run ex7
My name is Yoshio.

ふむ。
では、こうしたらどうなるだろう?

src/ex7/main.go

01: package main
02: 
03: import "fmt"
04: 
05: func main() {
06: 	{
07: 		defer fmt.Printf("Yoshio.\n")
08: 		defer fmt.Printf(" is ")
09: 		defer fmt.Printf("My name")
10: 	}
11: 	defer fmt.Printf("Mao.\n")
12: 	defer fmt.Printf(" are ")
13: 	defer fmt.Printf("You")
14: }
  

src$ go run ex7
You are Mao.
My name is Yoshio.

もしかしたらスコープを抜けるタイミングで実行されるんじゃないかと思ったのだが、returnするところまでリストに積んでから実行しているな。


deferは関数をリストに載せるものなら、こんなのでもよいのだろうか。

01: package main
02: 
03: import "fmt"
04: 
05: func main() {
06:     defer func() {
07:         fmt.Printf("My name")
08:         fmt.Printf(" is ")
09:         fmt.Printf("Yoshio.\n")
10:     }
11: }
  

無名関数、というやつかね(anonymous function、らしい)。

function must be invoked in defer statement

うーん、無名関数は関数ではないのだろうか?

01: package main
02: 
03: import "fmt"
04: 
05: func main() {
06:     defer func() {
07:         fmt.Printf("My name")
08:         fmt.Printf(" is ")
09:         fmt.Printf("Yoshio.\n")
10:     }()
11: }
  

ああ、括弧がこんなところに必要なのね!

src$ go run ex7
My name is Yoshio.

 

括弧に気付いたのはこちらのおかげだ。

go - Multiple defers vs deferred anonymous function - Stack Overflow
https://stackoverflow.com/posts/32541870/edit

そう、私もどっちがいいのか気になって、そもそも書けるのかどうかを試していたのだった。
順番が大切なら、anonymous functionにした方が意図が分かりやすいだろう。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。