ข้ามไปยังเนื้อหา

Packages และ Imports

ใน Go ทุก source file ต้องเริ่มต้นด้วย package declaration Package คือหน่วยของการจัดระเบียบ code ที่ Go ใช้ควบคุม scope และ visibility

package main // บอกว่า file นี้อยู่ใน package main

Package name ปกติจะสั้น, lowercase, และตรงกับชื่อ directory (เช่น directory stringspackage strings)

Program ที่ executable ต้องมี package main และ function func main() เสมอ เมื่อคุณรัน binary Go จะเริ่มต้นที่ main.main()

package main
func main() {
// program เริ่มต้นที่นี่
}

Package อื่น ๆ (เช่น library) ไม่มี func main แต่ถูก import ไปใช้โดย package อื่น

ใช้ 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"

Go ควบคุม visibility ด้วยตัวพิมพ์ของอักษรตัวแรกของ identifier:

Identifierตัวอย่างVisibility
ขึ้นต้นด้วยตัวพิมพ์ใหญ่fmt.Println, http.HandlerExported — ใช้ได้จาก package อื่น
ขึ้นต้นด้วยตัวพิมพ์เล็กmyHelper, internalMapUnexported — ใช้ได้เฉพาะใน package นั้น

กฎนี้ใช้กับ functions, types, variables, constants, และ struct fields ทั้งหมด

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 errors
  • sort — sort slices และ collections
  • math — math functions (Sqrt, Abs, Round)
  • time — time และ duration operations
  • os — 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, "."))
}
สิ่งที่ได้ประโยชน์ต้นทุน
uppercase = exportedvisibility rule เรียบง่าย ไม่ต้องใช้ keyword public/privateต้อง rename identifier ถ้าต้องการเปลี่ยน visibility
unused import = compile errorไม่มี dead import ใน codebaseต้องลบ import ที่ไม่ใช้ทุกครั้ง (goimports ช่วยได้)
init() functionsetup เกิดขึ้นอัตโนมัติhidden side effects ยากต่อการ debug และ test
module system (go.mod)reproducible build, explicit dependencylearning 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/sql driver register ตัวเองผ่าน init() — ทำให้ code ของ user สะอาดและไม่ต้อง explicit register

Package name ใดที่บอกว่า Go file นั้นจะ produce executable binary?
identifier ที่ขึ้นต้นด้วยตัวพิมพ์เล็กใน Go หมายความว่าอะไร?
เมื่อไรคุณจะใช้ blank import `import _ "pkg"`?
รูปแบบ idiomatic Go เมื่อ import หลาย package คือรูปแบบใด?