Error Handling and Defer

Back to Go Index

Error Handling

Error มี type เป็น interface จึงมี zero value คือ nil

Basic Error Handling

ลองใช้ Error handling กับการหารด้วย 0

func divide(a, b float64) (float64, error) {
	if b == 0 {
		err := fmt.Errorf("can't divide by zero")
		return 0, err
	}
	r := a / b
	return r, nil
}
 
func main() {
	r, err := divide(1, 0)
	if err != nil {
		fmt.Println("handler err:", err)
		return
	}
	fmt.Println(r, err)
}

Defer

เป็น keyword ที่ใช้ดำเนินการบางอย่างก่อนจบการทำงาน

  • เช่น การเปิด-ปิดไฟล์ สำหรับบางภาษาถ้าเปิดแล้วก็ต้องอย่าลืมปิดตอนท้ายด้วย ซึ่ง Defer จะเข้ามาช่วยโดยเมื่อเปิดไฟล์แล้วไม่มี error ก็สั่ง defer ปิดไฟล์ไว้ได้เลย
func main() {
	defer fmt.Println("Bye, World!")
 
	fmt.Println("Hello, World!")
}
 
// Hello, World!
// Bye, World!

Defer Stack Behavior

defer เป็น stack ซึ่งสามารถสั่งหลายครั้งซ้อนกันได้ โดยทำจากล่างขึ้นบน หรือหยิบของที่ใส่ไว้ล่าสุดมาก่อน

func main() {
	defer fmt.Println("defer#1")
	defer fmt.Println("defer#2")
	defer fmt.Println("defer#3")
 
	fmt.Println("Hello, World!")
}
 
// Hello, World!
// defer#3
// defer#2
// defer#1

Defer with Anonymous Function

การ Defer anonymous function

func main() {
	fmt.Println("counting")
	for i := 0; i < 3; i++ { // defer an anonymous function call
		defer func(n int) {
			fmt.Println(n)
		}(i)
	}
	fmt.Println("done")
 
	// Output:
	// counting
	// done
	// 2
	// 1
	// 0
}

Best Practices

File Handling Example

func readFile(filename string) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close() // Ensures file is closed when function returns
 
	// ... read file operations ...
	return nil
}

Database Connection Example

func queryDatabase() error {
	db, err := sql.Open("mysql", "connection-string")
	if err != nil {
		return err
	}
	defer db.Close() // Ensures connection is closed
 
	// ... database operations ...
	return nil
}

Related: