reflect, unsafe, cgo — รู้ไว้แต่เลี่ยงได้เลี่ยง
reflect ช้า + เสีย type safety, unsafe พังได้ทั้งโปรแกรมถ้า Go เปลี่ยนเวอร์ชัน, cgo build ยาก ไฟล์ใหญ่เหมาะกับงาน framework (แปลง struct <-> JSON/DB อัตโนมัติ):
import "reflect"
t := reflect.TypeOf(User{})
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
fmt.Println(f.Name, f.Tag.Get("json")) // อ่าน tag `json:"name"`
}
v := reflect.ValueOf(&u).Elem()
v.FieldByName("Name").SetString("Ann")ทริก: ถ้าเรียกบ่อยให้ cache Type/Field ไว้ อย่า reflect ทุกรอบ (ช้า) และถ้าใช้ JSON ใหม่ json/v2 + jsontext (1.27) อาจไม่ต้อง reflect เองแล้ว
ตัวอย่างคลาสสิก: แปลง string<->[]byte ไม่ก็อป (เร็วแต่เสี่ยง):
import "unsafe"
// เร็วเพราะไม่ก็อป แต่ถ้าแก้ bytes ต้นฉบับ string จะเปลี่ยนด้วย (แหกสัญญา immutable)
b := unsafe.Slice(unsafe.StringData(s), len(s))กฎ:
go vet + go fix (มี unsafefuncs เตือนจุดเสี่ยงใน 1.26-1.27) ก่อนส่งเสมอ// #include <stdio.h>
// #include <stdlib.h>
import "C"
import "unsafe"
cs := C.CString("hello")
defer C.free(unsafe.Pointer(cs))
C.puts(cs)GOEXPERIMENT=norandomizedheapbase64 เฉพาะตอนไล่บั๊กสาย cgo)CGO_ENABLED=0 ไปเลย ไฟล์เดียวจบ deploy ง่ายยังเป็น experimental ต้อง opt-in แต่อยากให้รู้ชื่อ (เดี๋ยวเป็นตัวจริงในอนาคต):
simd/archsimd — สั่ง CPU ทำหลายเลขพร้อมกัน เหมาะสายภาพ/เสียง/AIruntime/secret — ล้าง key ใน memory ให้เกลี้ยง กันหลุดไปอยู่ใน dump (สาย wallet/auth)runtime/pprof goroutineleak — จับ goroutine ที่ลืมปิดแล้วรั่ว ใช้คู่กับ testing/synctest (1.27) เทสต์ concurrent ไม่ flakyอ้างอิง: Go 1.26 (simd, secret, goroutineleak, cgo -30%, randomized heap), Go 1.27 (synctest), go fix unsafefuncs
type User struct {
Name string `json:"name"`
}
f, _ := reflect.TypeOf(User{}).FieldByName("Name")
fmt.Println(f.Tag.Get("json")) // nameunsafe ใช้แล้ว guarantee ของ GC หาย อัป Go อาจพัง — คอมเมนต์เหตุผลไว้ทุกจุดunsafe.Pointer ข้าม GC cycle ยาวๆgo fix unsafefuncs หลังอัปเวอร์ชันdump(v any) พิมพ์ field + tag ของ struct ใดๆgo vet กับโค้ด unsafe ดูว่าเตือนอะไร