[จดไว้กันลืม] Defer ใน Golang คืออะไร


  • Defer คือการสั่งให้ Function || Method นั้นๆ มีการทำงานหลังจากที่ Function main ทำงานเสร็จ หรืออีกความหมายคือ การสั่งให้ Function นั้นๆ ทำงานหลังสุดก่อนที่โปรแกรมจะปิด

การใช้งาน Defer

  • เริ่มจากการทำงานแบบ ปกติ
package main

import (
	"fmt"
)

func main() {
	fmt.Println("===== Start =====")
	name := "AA"
	hello(name)
	fmt.Println("===== End =====")
}

func hello(name string) {
	fmt.Printf("name => %s \n", name)
}
  • ผลลัพท์ที่ได้จะเป็น
$ go run .
...
===== Start =====
name => AA 
===== End =====
  • ในกรณีมีการใช้งาน defer
package main

import (
	"fmt"
)

func main() {
	fmt.Println("===== Start =====")
	name := "AA"
	defer hello(name)
	fmt.Println("===== End =====")
}

func hello(name string) {
	fmt.Printf("name => %s \n", name)
}
  • ผลลัพท์ ที่ได้จะเป็น
$ go run .
...
===== Start =====
===== End =====
name => AA

แล้วถ้าหากเรามีการใช้ defer หลายที่การทำงานจะเป็นยังไง

  • ยกตัวอย่างการทำงานแบบปกติ
package main

import (
	"fmt"
)

func main() {
	fmt.Println("===== Start =====")
	name := "AA"
	hello1(name)
	hello2(name)
	hello3(name)
	fmt.Println("===== End =====")
}

func hello1(name string) {
	fmt.Printf("name1 => %s \n", name)
}

func hello2(name string) {
	fmt.Printf("name2 => %s \n", name)
}

func hello3(name string) {
	fmt.Printf("name3 => %s \n", name)
}
  • ผลลัพท์ที่ได้จะเป็น
$ go run .
...
===== Start =====
name1 => AA 
name2 => AA 
name3 => AA 
===== End =====

Go โดยปกติจะมีการทำงานแบบจากบนลงล่างไปเรื่อยๆ

  • ใน กรณีมีการใช้ Defer
package main

import (
	"fmt"
)

func main() {
	fmt.Println("===== Start =====")
	name := "AA"
	defer hello1(name)
	defer hello2(name)
	defer hello3(name)
	fmt.Println("===== End =====")
}

func hello1(name string) {
	fmt.Printf("name1 => %s \n", name)
}

func hello2(name string) {
	fmt.Printf("name2 => %s \n", name)
}

func hello3(name string) {
	fmt.Printf("name3 => %s \n", name)
}
  • ผลลัพท์ที่ได้จะเป็น
$ go run .
...
===== Start =====
===== End =====
name3 => AA 
name2 => AA 
name1 => AA

การใช้ defer ลำดับมันก็จะตรงกันข้ามกับการทำงานปกติคือ จะทำงานจากตัวที่ใส่ defer ล่างสุดขึ้นไปข้างบน

  • หรือถ้าจะให้เห็นชัดขึ้น
package main

import (
	"fmt"
)

func main() {
	name := "AA"
	fmt.Println("===== Start =====")
	hello1(name)
	hello2(name)
	hello3(name)
	fmt.Println("===== End =====")

	defer fmt.Println("===== Start =====")
	defer hello1(name)
	defer hello2(name)
	defer hello3(name)
	defer fmt.Println("===== End =====")
}

func hello1(name string) {
	fmt.Printf("name1 => %s \n", name)
}

func hello2(name string) {
	fmt.Printf("name2 => %s \n", name)
}

func hello3(name string) {
	fmt.Printf("name3 => %s \n", name)
}
  • ผลลัพท์ที่ได้จะเป็น
$ go run .
...
===== Start =====
name1 => AA 
name2 => AA 
name3 => AA 
===== End =====
===== End =====
name3 => AA 
name2 => AA 
name1 => AA 
===== Start =====