หลังจากที่ Proposal เรื่อง Generic (Type Parameters) https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md ผ่านแล้ว อีกประมาณ 1 ปีก็จะออกมาให้ใช้ แต่ในระหว่างนี้เราก็ลองเล่นจาก branch dev.go2go
ได้ก็เลยได้หัดคิดว่าโค้ดแบบไหนที่ก่อนหน้านี้ที่เราใช้บ่อยๆ สามารถเอามาเรื่อง generic มาปรับปรุงได้ วันนี้เลยยกฟังก์ชัน Must ที่เราเห็นบ่อยๆในหลายๆ package มาลองเขียนด้วย generic ดู
ตัวอย่างเช่นใน package html/template
จะมีฟังก์ชัน Must
หน้าตาแบบนี้อยู่
func Must(t *Template, err error) *Template
ใน document เขียนบอกเอาไว้ว่า
Must is a helper that wraps a call to a function returning (*Template, error) and panics if the error is non-nil. It is intended for use in variable initializations such as
var t = template.Must(template.New("name").Parse("html"))
จะเห็นว่ามันก็เป็นฟังก์ชันที่รับผลลัพธ์จากการเรียกฟังก์ชันที่ return (*Template, error)
แล้วเช็คว่าถ้ามี error แล้วจะ panic ถ้าไม่มีก็ได้ *Template
กลับออกมาให้นั่นเอง เพื่อทำให้เราไม่ต้องเขียน if แบบนี้เอง
var t, err = template.New("name").Parse("html")
if err != nil {
panic(err)
}
อีกเหตุผลเพราะว่าเราเขียนแบบนี้ในตอนที่เราเรียกฟังก์ชันแล้วกำหนดค่าให้ตัวแปรใน package scope ไม่ได้ด้วยนั่นเอง
อย่างไรก็ตาม ถ้าเราคิดดีๆจะเห็นว่ามีอีกตั้งหลายครั้งที่เราเรียกฟังก์ชันแล้วได้ผลลัพธ์กลับออกมาพร้อม error เช่นตอนเรียก json.Marshal
b, err := json.Marshal(map[string]string{"msg": "Hello"})
if err != nil {
panic(err)
}
หรือตอนเรียก strconv.Atoi
num, err := strconv.Atoi("30")
if err != nil {
panic(err)
}
ซึ่งตอนที่ยังไม่มี generic เราต้องเขียน Must แยกเลยสำหรับแต่ละ type เช่นต้องมี Must([]byte, error)
สำหรับเคส json.Mashal
และ Must(int, error)
สำหรับเคส strconv.Atoi
เขียน Must แบบ Generic
ทีนี้เมื่อไหร่ก็ตามที่ Go รองรับ generic แล้วเราสามารถเขียน Must แค่รอบเดียวรองรับทั้ง 3 กรณีด้านบนได้เลยแบบนี้
func Must[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
คือเรากำหนด type parameter [T any]
แล้วเอา type T
ไปใช้เป็น parameter แรก แทนที่จะกำหนด type เจาะจงเองแบบก่อนหน้านี้
ทำให้เราใช้ func Must[T any](v T, err error) T
ที่เขียนแค่ครั้งเดียวนี้ได้กับที่ 3 กรณีด้านบนแบบนี้
var t = Must(template.New("name").Parse("html"))
var b = Must(json.Marshal(map[string]string{"msg": "Hello"}))
var num = Must(strconv.Atoi("30"))
ขอฝาก Buy Me a Coffee
สำหรับท่านใดที่อ่านแล้วชอบโพสต์ต่างๆของผมที่นี่ ต้องการสนับสนุนค่ากาแฟเล็กๆน้อยๆ สามารถสนับสนุนผมได้ผ่านทาง Buy Me a Coffee คลิ๊กที่รูปด้านล่างนี้ได้เลยครับ
ส่วนท่านใดไม่สะดวกใช้บัตรเครดิต หรือ Paypal สามารถสนับสนุนผมได้ผ่านทาง PromptPay โดยดู QR Code ได้จากโพสต์ที่พินเอาไว้ได้ที่ Page DevDose ครับ https://web.facebook.com/devdoseth
ขอบคุณครับ 🙏
Top comments (0)