อัปเดตล่าสุด: รองรับ Go เวอร์ชัน 1.22
Generics เป็นหนึ่งในฟีเจอร์ที่ถูกพูดถึงมานานใน Go และในที่สุดก็เปิดตัวอย่างเป็นทางการใน Go 1.18 และพัฒนาขึ้นต่อเนื่องถึง Go 1.22 ในบทความนี้เราจะมาเจาะลึกการใช้งาน Go Generics ทั้งพื้นฐานและเทคนิคขั้นสูง พร้อมตัวอย่างจริงที่สามารถนำไปใช้ได้ทันที
Generics คืออะไร?
Generics ช่วยให้เราสามารถเขียนโค้ดที่ใช้ซ้ำได้โดยไม่ต้องเจาะจงชนิดของข้อมูลล่วงหน้า โดยใช้ “type parameters” ทำให้เราสามารถทำงานกับหลายชนิดข้อมูลได้จากโค้ดเดียวกัน
ตัวอย่างที่ไม่ใช้ Generics
func DoubleInts(slice []int) []int { result := make([]int, len(slice)) for i, v := range slice { result[i] = v * 2 } return result }
ใช้ Generics แทนได้แบบนี้
func Map[T any](s []T, f func(T) T) []T { result := make([]T, len(s)) for i, v := range s { result[i] = f(v) } return result }
จากตัวอย่างด้านบน ฟังก์ชัน Map
สามารถใช้กับ slice ของอะไรก็ได้ ไม่ใช่แค่ []int
Syntax พื้นฐานของ Generics
การเขียน Generics จะใช้เครื่องหมาย [T any]
เพื่อประกาศพารามิเตอร์ชนิดข้อมูล (type parameter)
T
คือชื่อของพารามิเตอร์ชนิดข้อมูลany
หมายถึง T สามารถเป็นอะไรก็ได้
การใช้งานกับ Struct
type Box[T any] struct { Value T } func (b Box[T]) Get() T { return b.Value }
เรียกใช้งาน
intBox := Box[int]{Value: 10} fmt.Println(intBox.Get()) // 10 strBox := Box[string]{Value: "hello"} fmt.Println(strBox.Get()) // hello
การกำหนด Constraint
Generics ไม่ได้จำกัดแค่ type ที่เป็น any เราสามารถกำหนด constraint ได้ เช่น ตัวเลข หรือ type ที่มี method ใด ๆ
type Number interface { ~int | ~float64 } func Sum[T Number](a, b T) T { return a + b }
ในตัวอย่างนี้ T จะต้องเป็นชนิดข้อมูลที่สามารถบวกกันได้เท่านั้น
การใช้หลาย Type Parameter
func CompareAndPrint[K comparable, V any](m map[K]V) { for k, v := range m { fmt.Printf("%v => %v\n", k, v) } }
K
ต้องเป็น comparable
เพื่อใช้เป็น key ใน map ได้ ส่วน V
สามารถเป็นอะไรก็ได้
Generics กับ Method Receivers
type Pair[T any] struct { First, Second T } func (p Pair[T]) Swap() Pair[T] { return Pair[T]{First: p.Second, Second: p.First} }
Method Receiver ของ Struct ที่ใช้ Generics ก็สามารถใช้พารามิเตอร์ type ได้เช่นกัน
Best Practices ในการใช้ Go Generics
- ใช้ชื่อ type parameter สั้น เช่น T, K, V เว้นแต่จำเป็นต้องชัดเจน
- หลีกเลี่ยงการทำ constraint ซับซ้อนเกินไป
- ใช้ Generics เฉพาะกรณีที่ได้ประโยชน์จริง

อัปเดตล่าสุดใน Go 1.21 – 1.22
- ปรับปรุงการ infer type ให้ดีขึ้น
- รองรับ type sets ที่ซับซ้อนยิ่งขึ้น
- ใช้ constraint จาก interface เดิมที่ประกาศไว้ได้
ดู release note เพิ่มเติม: go.dev/doc/go1.22
สรุป
Go Generics เป็นฟีเจอร์ที่ทรงพลัง ช่วยให้เราสามารถเขียนโค้ดที่ยืดหยุ่น ปลอดภัย และ maintain ได้ง่ายขึ้นในระยะยาว โดยเฉพาะกับการเขียน reusable libraries และ data structure หากคุณยังไม่เคยลอง แนะนำให้เริ่มจากฟังก์ชันทั่วไปและค่อย ๆ ขยายไปใช้ใน Struct และ Method
แหล่งอ้างอิง
- Go Official Generics Tutorial
- Why Generics
- Go Playground (ทดลองเล่นโค้ด)
คำค้น (SEO Keywords)
- Go Generics
- Generics Go 1.22
- การใช้ Generics ในภาษา Go
- Go Generics Constraints
- Go Generics กับ Struct
- Generics Method Receiver
- type parameters Go