package.json เทียบกับ go.mod: ฟิลด์เวอร์ชันหายไปไหน?
หากคุณเปลี่ยนจาก JavaScript มาเป็น Go มีสิ่งหนึ่งที่จะทำให้คุณประหลาดใจ
ลองเปิดไฟล์ package.json ดู คุณจะเห็นฟิลด์ version อยู่ที่ด้านบนสุดเลย มันอ่านง่าย คุณสามารถแก้ไขมันผ่าน pull request ได้ และมันก็อยู่ในโค้ดของคุณนั่นเอง
คราวนี้ลองเปิดไฟล์ go.mod ดูบ้าง
คุณจะไม่พบเวอร์ชันอยู่ในนั้น นี่ไม่ใช่ความผิดพลาด แต่มันคือความตั้งใจในการออกแบบ
Go ไม่ใช้ฟิลด์เวอร์ชันสำหรับโมดูลของคุณเอง แต่จะใช้ git tags แทน
วิธีการทำงาน:
• คุณรัน git tag v1.2.3
• คุณ push tag นั้นไปยัง repository ของคุณ
• tag นั้นจะกลายเป็นเวอร์ชันของคุณ
เมื่อมีคนรัน go get ตัว Go จะไปดูที่ git tags ของคุณเพื่อหา commit ที่ถูกต้อง ดังนั้น tag จึงเป็นแหล่งข้อมูลความจริงเพียงหนึ่งเดียว (single source of truth)
การออกแบบนี้มีจุดแข็งที่สำคัญ คือเวอร์ชันจะไม่มีวันชี้ไปยังโค้ดที่ผิดพลาด ใน npm โค้ดที่ถูกเผยแพร่กับฟิลด์เวอร์ชันอาจคลาดเคลื่อนจากกันได้ แต่ใน Go ทั้งสองอย่างคือสิ่งเดียวกัน เวอร์ชันก็คือ commit นั่นเอง
อย่างไรก็ตาม สิ่งนี้จะเปลี่ยนเวิร์กโฟลว์ของคุณ:
- Visibility: คุณไม่สามารถดูเวอร์ชันได้จากการเปิดดูไฟล์ คุณต้องรันคำสั่ง git เพื่อค้นหา
- Code Reviews: การอัปเดตเวอร์ชัน (version bump) จะไม่ปรากฏใน code diff เพราะมันคือการ push tag ไม่ใช่การแก้ไขโค้ด
- Local Builds: commit ที่ไม่มี tag จะแสดงเป็น pseudo-version ที่ดูยุ่งเหยิง คุณจะได้เวอร์ชันที่ดูสะอาดตาหลังจากที่คุณทำการ tag commit นั้นแล้วเท่านั้น
- Major Versions: นี่คือการเปลี่ยนแปลงที่ใหญ่ที่สุด ใน Go เวอร์ชัน v2 ขึ้นไป จะต้องระบุเวอร์ชันไว้ใน import path ด้วย
ตัวอย่าง:
v1 ใช้ github.com/you/my-app
v2 ใช้ github.com/you/my-app/v2
สิ่งนี้ช่วยให้โปรแกรมเดียวสามารถใช้ไลบรารีเดียวกันคนละเวอร์ชันหลักได้โดยไม่เกิดความขัดแย้งกัน
ภาษาอื่นส่วนใหญ่จะเก็บเวอร์ชันไว้ในไฟล์:
• Node: package.json
• Rust: Cargo.toml
• Python: pyproject.toml
• Java: pom.xml
Go เป็นข้อยกเว้น เพราะมันพึ่งพา git tags อย่างเคร่งครัด
หากคุณคิดถึงประสบการณ์แบบ npm คุณสามารถฉีด (inject) เวอร์ชันเข้าไปใน binary ของคุณในขณะ build ได้โดยใช้ ldflags ซึ่งจะช่วยให้แอปของคุณสามารถตอบสนองต่อคำสั่งเรียกดูเวอร์ชันได้
ข้อแลกเปลี่ยนนั้นเรียบง่าย: ฟิลด์เวอร์ชันนั้นอ่านและรีวิวได้ง่าย แต่ก็อาจให้ข้อมูลที่ไม่เป็นจริงได้ git tag นั้นมองเห็นได้ยาก แต่ข้อมูลจะเป็นความจริงเสมอ
Go เลือกความถูกต้องมากกว่าความสะดวกสบาย
ถึงเหล่านักพัฒนา Go: นี่คือโมเดลที่ดีที่สุดแล้วหรือยัง? คุณจะชอบให้มีฟิลด์เวอร์ชันใน go.mod มากกว่าไหม ถ้าหากเครื่องมือต่างๆ สามารถตรวจสอบความถูกต้องเทียบกับ git tag ได้?
ที่มา: https://dev.to/dalirnet/packagejson-vs-gomod-where-did-the-version-field-go-3301