Go 1.27 ให้ go test จับ API ใหม่เกิน go.mod ด้วย stdversion
เครื่อง developer มี Go ใหม่กว่า CI ได้เสมอ ปัญหาคือโค้ดอาจเรียก standard library ที่เพิ่งเพิ่มใหม่ ทั้งที่ go.mod ยังประกาศรองรับเวอร์ชันเก่า แล้วทุกอย่างผ่านบนเครื่องคนเขียนแต่พังใน runner ครับ Go 1.27 ลดช่องว่างนี้โดยให้ go test เรียกตัวตรวจ stdversion เป็นค่าเริ่มต้น
WHY: go.mod คือสัญญา ไม่ใช่ป้ายตกแต่ง
บรรทัด go ใน go.mod บอก language semantics และเวอร์ชันมาตรฐานที่โมดูลตั้งใจใช้ หากทีมประกาศเวอร์ชันหนึ่งแต่ source เรียก symbol ที่ใหม่กว่า ผู้ใช้ downstream จะพบปัญหาตอน build ช้ากว่าจุดที่เราแก้ได้ง่าย
Release notes ของ Go 1.27 ระบุว่า go test เปิด stdversion ในชุด vet ความมั่นใจสูงแล้ว ตัวตรวจจะเทียบ symbol กับเวอร์ชันที่มีผลจาก go.mod และ build tags จึงไม่ต้องเพิ่ม linter ภายนอกเพียงเพื่อเช็กเรื่องนี้
HOW: เขียน test ปกติแล้วให้ gate เดิมทำงานเพิ่ม
ตัวอย่างใช้ strings.SplitSeq และทดสอบผลลัพธ์จริง โมดูลที่ประกาศ Go 1.27 ผ่านทั้ง compile, vet และ test ในคำสั่งเดียว
package words
import (
"slices"
"strings"
"testing"
)
func FieldsByComma(input string) []string {
return slices.Collect(strings.SplitSeq(input, ","))
}
func TestFieldsByComma(t *testing.T) {
got := FieldsByComma("mint,teal,amber")
want := []string{"mint", "teal", "amber"}
if !slices.Equal(got, want) {
t.Fatalf("got %v, want %v", got, want)
}
}
ใน repository จริงให้รัน go test ./... เหมือนเดิม ถ้าลด directive ไปเป็นเวอร์ชันก่อนที่ symbol จะมี ตัวตรวจจะรายงานการใช้ API ใหม่เกินสัญญาก่อน test binary ทำงาน นี่ต่างจากการลอง compile ด้วย Go รุ่นเก่า เพราะ developer ไม่ต้องติดตั้ง toolchain หลายชุดเพื่อเห็นความผิดพลาดพื้นฐาน
จุดที่ต้องระวัง
stdversion ไม่ยืนยันว่า dependency ภายนอกรองรับ runtime ทุกระบบ และไม่แทน matrix CI บน compiler ต่ำสุด มันตรวจเฉพาะ symbol ของ standard library กับเวอร์ชันที่ประกาศเท่านั้น งานที่พึ่ง cgo, build tags หลาย OS หรือ behavior ที่เปลี่ยนตาม patch ยังต้องทดสอบบน target จริง
อย่าปิด vet ทั้งชุดด้วย -vet=off เพื่อให้ pipeline เขียว หากมี false positive ให้สร้าง reproduction เล็กและรายงาน upstream การปิดทั้งหมดจะทำให้เสียทั้ง printf, errorsas, stdversion และตัวตรวจอื่นที่ go test เลือกไว้
Recap
- ตั้ง
godirective ให้ตรงเวอร์ชันต่ำสุดที่ทีมสนับสนุนจริง - รัน
go test ./...ใน PR ทุกครั้ง - เก็บ CI job ที่ใช้ toolchain ต่ำสุดไว้ตรวจ platform และ behavior เพิ่ม
- อัป directive กับการเริ่มใช้ API ใหม่ใน PR เดียวกัน
พรุ่งนี้ลองค้น -vet=off ใน pipeline ก่อนหนึ่งจุด แล้วคืนค่า go test ปกติเพื่อให้ stdversion ช่วยเฝ้าสัญญาครับ