DEV Community

Weerasak Chongnguluam
Weerasak Chongnguluam

Posted on

1

ลองเขียน Must ฟังก์ชันในแบบ generic ของ Go

#go

หลังจากที่ 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
Enter fullscreen mode Exit fullscreen mode

ใน 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"))
Enter fullscreen mode Exit fullscreen mode

จะเห็นว่ามันก็เป็นฟังก์ชันที่รับผลลัพธ์จากการเรียกฟังก์ชันที่ return (*Template, error) แล้วเช็คว่าถ้ามี error แล้วจะ panic ถ้าไม่มีก็ได้ *Template กลับออกมาให้นั่นเอง เพื่อทำให้เราไม่ต้องเขียน if แบบนี้เอง

var t, err = template.New("name").Parse("html")
if err != nil {
        panic(err)
}
Enter fullscreen mode Exit fullscreen mode

อีกเหตุผลเพราะว่าเราเขียนแบบนี้ในตอนที่เราเรียกฟังก์ชันแล้วกำหนดค่าให้ตัวแปรใน package scope ไม่ได้ด้วยนั่นเอง

อย่างไรก็ตาม ถ้าเราคิดดีๆจะเห็นว่ามีอีกตั้งหลายครั้งที่เราเรียกฟังก์ชันแล้วได้ผลลัพธ์กลับออกมาพร้อม error เช่นตอนเรียก json.Marshal

b, err := json.Marshal(map[string]string{"msg": "Hello"})
if err != nil {
        panic(err)
}
Enter fullscreen mode Exit fullscreen mode

หรือตอนเรียก strconv.Atoi

num, err := strconv.Atoi("30")
if err != nil {
        panic(err)
}
Enter fullscreen mode Exit fullscreen mode

ซึ่งตอนที่ยังไม่มี 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
}
Enter fullscreen mode Exit fullscreen mode

คือเรากำหนด 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"))
Enter fullscreen mode Exit fullscreen mode

ขอฝาก Buy Me a Coffee

สำหรับท่านใดที่อ่านแล้วชอบโพสต์ต่างๆของผมที่นี่ ต้องการสนับสนุนค่ากาแฟเล็กๆน้อยๆ สามารถสนับสนุนผมได้ผ่านทาง Buy Me a Coffee คลิ๊กที่รูปด้านล่างนี้ได้เลยครับ

Buy Me A Coffee

ส่วนท่านใดไม่สะดวกใช้บัตรเครดิต หรือ Paypal สามารถสนับสนุนผมได้ผ่านทาง PromptPay โดยดู QR Code ได้จากโพสต์ที่พินเอาไว้ได้ที่ Page DevDose ครับ https://web.facebook.com/devdoseth

ขอบคุณครับ 🙏

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay