อัปเดตล่าสุด: รองรับ 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