Go Modules
Go module คืออะไร?
หัวข้อที่มีชื่อว่า “Go module คืออะไร?”module คือกลุ่มของ Go packages ที่มี version ร่วมกันและแจกจ่ายเป็นหน่วยเดียว โปรเจกต์ Go สมัยใหม่ทุกโปรเจกต์เริ่มต้นด้วย module ระบบ module แทนที่ workflow GOPATH แบบเก่าใน Go 1.11 และกลายเป็นค่าเริ่มต้นใน Go 1.16
Playground note: คำสั่ง
go modต้องการgobinary และ file system — ไม่สามารถรันใน in-browser runner ได้ ให้ทำตามขั้นตอนด้านล่างใน terminal ของคุณ
การ initialise module
หัวข้อที่มีชื่อว่า “การ initialise module”mkdir myapp && cd myappgo mod init github.com/yourname/myappคำสั่งนี้สร้างไฟล์ go.mod — manifest ของ module:
module github.com/yourname/myapp
go 1.22module path (github.com/yourname/myapp) ทำหน้าที่ทั้งเป็น import path prefix สำหรับ packages ของคุณเองและเป็น identifier ที่ modules อื่นใช้เมื่อ depend บน module ของคุณ ไม่จำเป็นต้องเป็น URL จริงระหว่าง development แต่ต้องไม่ซ้ำกันหากคุณเผยแพร่ใน Go module proxy
go.mod และ go.sum
หัวข้อที่มีชื่อว่า “go.mod และ go.sum”หลังจากเพิ่ม dependency คุณจะพบสองไฟล์ใน root ของ module:
go.mod — ประกาศ module path, Go version ขั้นต่ำ, และ dependencies ทั้งหมดทั้งทางตรงและทางอ้อม:
module github.com/yourname/myapp
go 1.22
require ( github.com/go-chi/chi/v5 v5.1.0 golang.org/x/text v0.14.0 // indirect)go.sum — ทะเบียน cryptographic checksum ทุก zip archive ของ dependency และ go.mod ถูก hash ที่นี่ Go toolchain ตรวจสอบ hash เหล่านี้ทุก build เพื่อรับประกัน reproducibility และป้องกัน supply-chain attacks ให้ commit ทั้งสองไฟล์ลง version control
การเพิ่ม dependency
หัวข้อที่มีชื่อว่า “การเพิ่ม dependency”# เพิ่ม module เวอร์ชันล่าสุดgo get github.com/go-chi/chi/v5
# เพิ่มเวอร์ชันที่ระบุ
# อัปเกรด dependency เป็น patch/minor release ล่าสุดgo get -u github.com/go-chi/chi/v5หลังจาก go get source code ของคุณสามารถ import package ได้:
import "github.com/go-chi/chi/v5"go mod tidy
หัวข้อที่มีชื่อว่า “go mod tidy”เมื่อเวลาผ่านไป code และ dependencies อาจไม่สอดคล้องกัน — คุณอาจลบ import หรือเพิ่มโดยไม่ได้รัน go get go mod tidy แก้ไขทั้งสองกรณี:
go mod tidyคำสั่งนี้เพิ่ม require lines ที่ขาดหาย ลบ require lines สำหรับ packages ที่ไม่ได้ import แล้ว และอัปเดต go.sum ให้ตรงกัน รันก่อน commit ทุกครั้ง
Semantic import versioning
หัวข้อที่มีชื่อว่า “Semantic import versioning”Go บังคับใช้กฎที่เรียกว่า semantic import versioning: หาก module ออก v2 ขึ้นไป import path ต้องรวม major version suffix ด้วย
# v1 — ไม่ต้องใช้ suffix# import "github.com/foo/bar"
# v2+ — /v2 suffix เป็นส่วนหนึ่งของ import path# import "github.com/foo/bar/v2"ซึ่งหมายความว่า major version สองเวอร์ชันของ module เดียวกันสามารถอยู่ร่วมกันใน binary เดียวได้โดยไม่ขัดแย้ง การเปลี่ยน import path เป็นเจตนา: v2 API อนุญาตให้ไม่เข้ากันกับ v1
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| สิ่งที่ได้ | ประโยชน์ | ต้นทุน |
|---|---|---|
go.mod (explicit versioning) | reproducible build, dependency ชัดเจน | ต้อง update เมื่อ dependency เปลี่ยน — go mod tidy บ่อยๆ |
| semantic versioning | backward compatibility contract ชัดเจน | major version bump ทำ import path เปลี่ยน — migration cost |
go.sum (hash verification) | ป้องกัน supply chain attack, verify integrity | ต้อง commit go.sum ด้วย — หลายคนลืม |
go mod vendor | air-gapped build ได้, ไม่ต้องพึ่ง network | vendor/ directory ใหญ่, ต้อง sync ทุก dependency update |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”go getเหมือนnpm install—go getupdatego.modและ download source ไม่ install binary แยก ต่างจาก npm มาก- สามารถ ignore
go.sum—go.sumต้อง commit ร่วมกับgo.modเพื่อ verify dependency integrity — ถ้าขาด build อาจไม่ reproducible replacedirective ใช้ใน production ได้ —replacedirective ควรเป็น temporary เท่านั้น (เช่น local testing) ไม่ควรอยู่ใน productiongo.modGOPATH/pkg/modเป็น module cache ถาวร —go clean -modcacheล้าง cache ได้ — ไม่ใช่ permanent storage ควร treat เป็น cache
💡 ตัวอย่างจากของจริง
Kubernetes มี
go.modที่มี dependency หลักร้อยตัว —vendor/ถูก commit เพื่อให้ build reproducible ในทุก environmentGo ecosystem: semantic versioning +
go.sumhash verification ทำให้ supply chain attack ยากขึ้นมาก — Kubernetes, Docker, Prometheus ทั้งหมด depend on thisDocker: multi-stage Dockerfile ใช้
go mod downloadก่อน copy source เพื่อ cache layer — rebuild เร็วขึ้นมากเมื่อ source เปลี่ยนแต่ dependency ไม่เปลี่ยน