Packages และ Imports
Package คืออะไร?
หัวข้อที่มีชื่อว่า “Package คืออะไร?”ใน Go ทุก source file ต้องเริ่มต้นด้วย package declaration Package คือหน่วยของการจัดระเบียบ code ที่ Go ใช้ควบคุม scope และ visibility
package main // บอกว่า file นี้อยู่ใน package mainPackage name ปกติจะสั้น, lowercase, และตรงกับชื่อ directory (เช่น directory strings → package strings)
func main — จุดเริ่มต้น
หัวข้อที่มีชื่อว่า “func main — จุดเริ่มต้น”Program ที่ executable ต้องมี package main และ function func main() เสมอ เมื่อคุณรัน binary Go จะเริ่มต้นที่ main.main()
package main
func main() { // program เริ่มต้นที่นี่}Package อื่น ๆ (เช่น library) ไม่มี func main แต่ถูก import ไปใช้โดย package อื่น
การ Import
หัวข้อที่มีชื่อว่า “การ Import”ใช้ import เพื่อดึง package อื่นเข้ามาใช้ มีสองรูปแบบ:
// import เดี่ยวimport "fmt"
// grouped import (แนะนำเมื่อ import หลาย package)import ( "fmt" "strings" "strconv")Go compiler จะ error ทันทีถ้าคุณ import package แล้วไม่ใช้ สิ่งนี้บังคับให้ code สะอาด
หากต้องการ import package เพื่อ side effect เท่านั้น (เช่น init() ของ package นั้น) ใช้ blank identifier:
import _ "net/http/pprof"Exported vs Unexported
หัวข้อที่มีชื่อว่า “Exported vs Unexported”Go ควบคุม visibility ด้วยตัวพิมพ์ของอักษรตัวแรกของ identifier:
| Identifier | ตัวอย่าง | Visibility |
|---|---|---|
| ขึ้นต้นด้วยตัวพิมพ์ใหญ่ | fmt.Println, http.Handler | Exported — ใช้ได้จาก package อื่น |
| ขึ้นต้นด้วยตัวพิมพ์เล็ก | myHelper, internalMap | Unexported — ใช้ได้เฉพาะใน package นั้น |
กฎนี้ใช้กับ functions, types, variables, constants, และ struct fields ทั้งหมด
Standard Library
หัวข้อที่มีชื่อว่า “Standard Library”Go มี standard library ที่ครบครันในตัว package ที่ใช้บ่อย ได้แก่:
fmt— formatted I/O (Println, Printf, Sprintf, Errorf)strings— string manipulation (ToUpper, Split, Join, Contains, Replace)strconv— แปลงระหว่าง string และ numeric types (Itoa, Atoi, ParseFloat)errors— สร้างและ wrap errorssort— sort slices และ collectionsmath— math functions (Sqrt, Abs, Round)time— time และ duration operationsos— OS interface (file I/O, environment variables)
package main
import ( "fmt" "strconv" "strings")
func main() { // fmt: formatted output fmt.Println("Go packages demo")
// strings: manipulating text sentence := "the quick brown fox" words := strings.Split(sentence, " ") fmt.Println("Word count:", len(words)) fmt.Println("Uppercase:", strings.ToUpper(sentence)) fmt.Println("Contains 'fox':", strings.Contains(sentence, "fox"))
// strconv: converting between strings and numbers n := 42 s := strconv.Itoa(n) fmt.Println("int to string:", s)
parsed, err := strconv.Atoi("123") if err == nil { fmt.Println("string to int:", parsed) }
// Combining packages together parts := []string{"Go", strconv.Itoa(1), strconv.Itoa(22)} fmt.Println("Joined:", strings.Join(parts, "."))}Loading Go runtime (first run only, ~8 MB)…
ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| สิ่งที่ได้ | ประโยชน์ | ต้นทุน |
|---|---|---|
| uppercase = exported | visibility rule เรียบง่าย ไม่ต้องใช้ keyword public/private | ต้อง rename identifier ถ้าต้องการเปลี่ยน visibility |
| unused import = compile error | ไม่มี dead import ใน codebase | ต้องลบ import ที่ไม่ใช้ทุกครั้ง (goimports ช่วยได้) |
init() function | setup เกิดขึ้นอัตโนมัติ | hidden side effects ยากต่อการ debug และ test |
| module system (go.mod) | reproducible build, explicit dependency | learning curve สูงกว่า GOPATH เดิม |
ความเข้าใจผิดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ความเข้าใจผิดที่พบบ่อย”- “circular import ใช้ได้ใน test files” — Go ไม่อนุญาต circular import ไม่ว่าจะเป็น production code หรือ test files
- “
import _ใช้ได้แค่กับ database driver” — ใช้ได้กับทุก package ที่ต้องการให้init()ทำงาน เช่น register codec, plugin, หรือ HTTP handler - “Go module คือแค่ package manager เหมือน npm” — Go module จัดการ versioning และ reproducible build ที่ระดับ module ทั้งหมด ไม่ใช่แค่ package เดี่ยว
💡 ตัวอย่างจากของจริง
Kubernetes จัดระเบียบ codebase หลายล้านบรรทัดด้วย package structure ที่ชัดเจน — แต่ละ package มีความรับผิดชอบเดียว ทำให้ team ขนาดใหญ่ทำงานร่วมกันได้
Go standard library เช่น
net/httpใช้ blank import ให้database/sqldriver register ตัวเองผ่านinit()— ทำให้ code ของ user สะอาดและไม่ต้อง explicit register