0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

defer基本使い方

Posted at

基本的な使用方法

deferキーワードは通常、リソースのオープン後に配置され、後でリソースを閉じることを忘れないようにします。
deferで宣言されたコードは、実際には関数が終了するまで実行されません。

func demo_defer_0() {
	fileName := "./test.txt"
	f, _ := os.OpenFile(fileName, os.O_RDONLY, 0)
	defer f.Close()

	contents, _ := ioutil.ReadAll(f)
	fmt.Println(string(contents))
}

複数のdefer呼び出しの順序:先入れ後出し(FILO)

func demo_defer_1() {
	for i := 0; i < 3; i++ {
		defer fmt.Println("defer:", i)
	}
}

// defer: 2
// defer: 1
// defer: 0

スコープは現在の関数に制限されます


異なる関数には異なる関数スタックがあります。

func demo_defer_2() {
	func() {
		defer fmt.Println(1)
		defer fmt.Println(2)
	}()

	fmt.Println("defer action")

	func() {
		defer fmt.Println("a")
		defer fmt.Println("b")
	}()
}

// 2
// 1
// defer action
// b
// a

deferの後の関数パラメータは値渡しです

func demo_defer_3_1() {
	num := 0
	defer func(n int) {
		fmt.Println("defer:", n)
	}(num)

	for i := 0; i < 10; i++ {
		num++
	}

	fmt.Println(num)
}


// 10
// defer: 0
func demo_defer_3_2() {
	num := 0
	p := &num
	defer func(p *int) {
		fmt.Println("defer:", *p)
	}(p)

	for i := 0; i < 10; i++ {
		num++
	}

	fmt.Println(*p)
}

// 10
// defer: 10
func demo_defer_3_3() {
	num := 0
	defer func() {
		fmt.Println("defer:", num)
	}()

	for i := 0; i < 10; i++ {
		num++
	}

	fmt.Println(num)
}

// 10
// defer: 10

returnはdeferより先に実行されます

func demo_defer_4_1() (int, error) {
	defer fmt.Println("defer")
	return fmt.Println("return")
}

// return
// defer
func demo_defer_4_2() (num int) {
	num = 10
	defer func() {
		num += 5
	}()

	return 2
}

// 7

最初に(num int)で、numは初期値0です。
その後、num = 10として、値が10に設定されます。
次に、return 2で、numが2に設定されます。
最後に、deferの中でnumが計算され、結果は7です。

func demo_defer_4_3() int {
	num := 10
	defer func() {
		num += 5
	}()

	return 2
}

// 2

ここでは、numとreturnの値は関連していません。

panicが発生した場合、既に宣言されたdeferはスタックから実行されます

func demo_defer_5_1() {
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)

	panic("panic call")

	defer fmt.Println(4) // 実行されません
}
func demo_defer_5_2() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
		}
	}()

	panic("panic call")
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?