Go หรือที่รู้จักกันในชื่อ Golang เป็นภาษาโปรแกรมมิ่งที่สร้างโดย Google ในปี 2009 โดยทีมวิศวกรระดับตำนานอย่าง Robert Griesemer, Rob Pike และ Ken Thompson ผู้สร้าง Unix และภาษา C มาก่อน เป้าหมายของ Go คือการสร้างภาษาที่เรียบง่าย รวดเร็ว และรองรับการทำงานแบบ Concurrent ได้อย่างยอดเยี่ยม ซึ่งในปี 2026 Go กลายเป็นภาษายอดนิยมอันดับต้นๆ สำหรับการพัฒนา Backend, Microservices, Cloud Infrastructure และ DevOps Tools
บทความนี้จะพาคุณเรียนรู้ Go ตั้งแต่เริ่มต้นจนถึงขั้นสร้าง REST API ได้ด้วยตัวเอง ครอบคลุมทุกหัวข้อสำคัญ ไม่ว่าจะเป็น Syntax พื้นฐาน, Goroutines, Channels, Error Handling, Modules, Standard Library และ Framework ยอดนิยมอย่าง Gin, Echo, Fiber
ทำไมต้อง Go? จุดเด่นที่ทำให้โดดเด่น
Go ไม่ได้เป็นแค่ภาษาใหม่อีกภาษาหนึ่ง แต่เป็นภาษาที่ออกแบบมาเพื่อแก้ปัญหาจริงของการพัฒนาซอฟต์แวร์ในระดับใหญ่ หลายบริษัทยักษ์ใหญ่เลือกใช้ Go เป็นภาษาหลักด้วยเหตุผลสำคัญหลายประการ
ความเร็วในการ Compile และ Execute — Go เป็นภาษา Compiled ที่ Compile เร็วมากเมื่อเทียบกับ C/C++ แต่ประสิทธิภาพการทำงานใกล้เคียงกัน โปรแกรม Go ทำงานเร็วกว่า Python 40-50 เท่า และเร็วกว่า Node.js ประมาณ 5-10 เท่าในงาน CPU-intensive
Concurrency ที่ง่ายดาย — Goroutines คือฟีเจอร์เด่นที่สุดของ Go สามารถสร้าง Goroutine ได้หลายแสนตัวในโปรแกรมเดียว โดยใช้ Memory เพียง 2KB ต่อ Goroutine เทียบกับ Thread ของ OS ที่ใช้ 1-2MB ทำให้ Go เหมาะกับงาน Web Server ที่ต้องรองรับ Request จำนวนมากพร้อมกัน
ความเรียบง่าย — Go มี Keyword เพียง 25 ตัว ไม่มี Class, Inheritance, Generic (มีแล้วใน Go 1.18+), ไม่มี Exception ใช้ Error Return แทน ทำให้ Code อ่านง่ายและ Maintain ง่าย ทุกคนในทีมเขียน Code ออกมาหน้าตาเหมือนกัน
Static Binary — Go Compile ออกมาเป็นไฟล์ Binary เดียว ไม่ต้องติดตั้ง Runtime หรือ Dependencies เพิ่มเติม ทำให้ Deploy ง่ายมาก โดยเฉพาะในสภาพแวดล้อม Container อย่าง Docker
Standard Library ที่ทรงพลัง — Go มาพร้อม Standard Library ที่ครอบคลุมเกือบทุกอย่าง ตั้งแต่ HTTP Server, JSON, Cryptography, Database, Testing โดยไม่ต้องพึ่ง Third-party Library มากนัก
ใครใช้ Go บ้าง?
บริษัทระดับโลกมากมายใช้ Go เป็นภาษาหลักในระบบ Production ของตน:
- Google — ผู้สร้าง Go เอง ใช้ในระบบภายในมากมาย รวมถึง Kubernetes
- Docker — Container Platform ที่เปลี่ยนโลก DevOps เขียนด้วย Go ทั้งหมด
- Kubernetes — Container Orchestration อันดับ 1 เขียนด้วย Go
- Uber — ใช้ Go สำหรับ Microservices ที่ต้องรองรับ Request หลายล้านครั้งต่อวินาที
- Twitch — ใช้ Go สำหรับ Chat System และ Video Distribution
- Cloudflare — ใช้ Go สำหรับ Edge Network Infrastructure
- Terraform, Prometheus, Grafana, etcd — เครื่องมือ DevOps ยอดนิยมล้วนเขียนด้วย Go
ติดตั้ง Go
# Windows — ดาวน์โหลดจาก https://go.dev/dl/
# เลือก .msi installer แล้วติดตั้งตามปกติ
# macOS
brew install go
# Linux (Ubuntu/Debian)
sudo apt update
sudo apt install golang-go
# หรือดาวน์โหลด Official Binary
wget https://go.dev/dl/go1.23.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
# ตรวจสอบการติดตั้ง
go version
go env GOPATH
go env GOROOT
โปรแกรม Go แรกของคุณ
# สร้างโปรเจกต์
mkdir hello-go && cd hello-go
go mod init hello-go
# สร้างไฟล์ main.go
// main.go
package main
import "fmt"
func main() {
fmt.Println("สวัสดี Go! Hello, World!")
}
# รัน
go run main.go
# Build เป็น Binary
go build -o hello main.go
./hello
Syntax พื้นฐานของ Go
ตัวแปรและชนิดข้อมูล
package main
import "fmt"
func main() {
// ประกาศตัวแปรแบบระบุ Type
var name string = "Go"
var age int = 17
var price float64 = 99.99
var active bool = true
// Short declaration (:=) — ใช้ได้เฉพาะในฟังก์ชัน
language := "Golang"
version := 1.23
count := 42
// Constants
const Pi = 3.14159
const AppName = "MyApp"
// Multiple variables
var (
x int = 10
y int = 20
z string = "hello"
)
// Zero values (ค่าเริ่มต้น)
var i int // 0
var f float64 // 0.0
var s string // ""
var b bool // false
fmt.Println(name, age, price, active)
fmt.Println(language, version, count)
fmt.Printf("Pi = %.2f\n", Pi)
fmt.Println(x, y, z, i, f, s, b)
}
ฟังก์ชัน (Functions)
// ฟังก์ชันพื้นฐาน
func greet(name string) string {
return "Hello, " + name
}
// Multiple return values — จุดเด่นของ Go
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, fmt.Errorf("cannot divide by zero")
}
return a / b, nil
}
// Named return values
func swap(a, b int) (x, y int) {
x = b
y = a
return // naked return
}
// Variadic function (รับ arguments ไม่จำกัด)
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
// ใช้งาน
func main() {
msg := greet("World")
result, err := divide(10, 3)
if err != nil {
fmt.Println("Error:", err)
}
a, b := swap(1, 2)
total := sum(1, 2, 3, 4, 5)
fmt.Println(msg, result, a, b, total)
}
Arrays, Slices และ Maps
// Array — ขนาดคงที่
var arr [5]int = [5]int{1, 2, 3, 4, 5}
// Slice — ขนาดยืดหยุ่น (ใช้บ่อยกว่า Array)
fruits := []string{"apple", "banana", "cherry"}
fruits = append(fruits, "durian")
fmt.Println(fruits[1:3]) // [banana cherry]
fmt.Println(len(fruits)) // 4
// Make slice with capacity
numbers := make([]int, 0, 10)
numbers = append(numbers, 1, 2, 3)
// Map — key-value pairs
scores := map[string]int{
"Alice": 95,
"Bob": 87,
"Carol": 92,
}
scores["Dave"] = 88
// ตรวจสอบ key มีอยู่หรือไม่
score, exists := scores["Eve"]
if !exists {
fmt.Println("Eve not found")
}
// ลบ key
delete(scores, "Bob")
// วนลูป Map
for name, score := range scores {
fmt.Printf("%s: %d\n", name, score)
}
Control Flow
// if-else
if age >= 18 {
fmt.Println("Adult")
} else if age >= 13 {
fmt.Println("Teen")
} else {
fmt.Println("Child")
}
// if with initialization
if err := doSomething(); err != nil {
fmt.Println("Error:", err)
}
// for loop (Go มีแค่ for ไม่มี while)
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// for เหมือน while
count := 0
for count < 10 {
count++
}
// infinite loop
for {
// ใช้ break เพื่อออก
break
}
// range loop
for index, value := range fruits {
fmt.Printf("[%d] %s\n", index, value)
}
// switch
switch day {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
fmt.Println("Weekday")
case "Saturday", "Sunday":
fmt.Println("Weekend")
default:
fmt.Println("Unknown")
}
Structs — โครงสร้างข้อมูล
Go ไม่มี Class แต่ใช้ Struct แทน ซึ่งเป็นวิธีจัดกลุ่มข้อมูลที่เกี่ยวข้องเข้าด้วยกัน และสามารถเพิ่ม Method ให้ Struct ได้
// กำหนด Struct
type User struct {
ID int
Name string
Email string
Age int
IsActive bool
}
// Method ของ Struct (value receiver)
func (u User) FullInfo() string {
return fmt.Sprintf("%s (%s), age %d", u.Name, u.Email, u.Age)
}
// Method ที่แก้ไขค่าได้ (pointer receiver)
func (u *User) Deactivate() {
u.IsActive = false
}
// Constructor function (Go convention)
func NewUser(id int, name, email string, age int) *User {
return &User{
ID: id,
Name: name,
Email: email,
Age: age,
IsActive: true,
}
}
func main() {
user := NewUser(1, "Somchai", "somchai@example.com", 30)
fmt.Println(user.FullInfo())
user.Deactivate()
fmt.Println("Active:", user.IsActive)
}
Interfaces — พลังแห่งความยืดหยุ่น
Interface ใน Go เป็น Implicit Interface คือไม่ต้องประกาศว่า Implement Interface ไหน แค่มี Method ตรงก็ใช้ได้เลย ซึ่งเป็นหนึ่งในแนวคิดที่ทรงพลังที่สุดของ Go
// กำหนด Interface
type Shape interface {
Area() float64
Perimeter() float64
}
// Rectangle implements Shape (implicitly)
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
// Circle implements Shape (implicitly)
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * c.Radius
}
// ฟังก์ชันที่รับ Interface
func PrintShape(s Shape) {
fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}
func main() {
rect := Rectangle{Width: 10, Height: 5}
circle := Circle{Radius: 7}
PrintShape(rect) // ใช้ได้เพราะ Rectangle มี Method ตรง
PrintShape(circle) // ใช้ได้เพราะ Circle มี Method ตรง
// Empty Interface — รับค่าอะไรก็ได้ (เหมือน any)
var anything interface{}
anything = 42
anything = "hello"
anything = true
fmt.Println(anything)
}
Goroutines — Concurrency ที่ง่ายที่สุด
Goroutines คือ Lightweight Threads ที่จัดการโดย Go Runtime ไม่ใช่ OS Thread โดยตรง ทำให้สามารถสร้างได้เป็นหมื่นเป็นแสนตัวโดยไม่เปลือง Memory มากนัก การสร้าง Goroutine ง่ายมาก แค่ใส่คำว่า go หน้าฟังก์ชัน
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done()
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
for i := 1; i <= 5; i++ {
wg.Add(1)
go worker(i, &wg) // สร้าง Goroutine ด้วย go keyword
}
wg.Wait() // รอทุก Goroutine ทำงานเสร็จ
fmt.Println("All workers completed")
}
Channels — สื่อสารระหว่าง Goroutines
Channels เป็นท่อส่งข้อมูลระหว่าง Goroutines ทำให้สื่อสารกันได้อย่างปลอดภัย ไม่ต้องใช้ Lock หรือ Mutex โดยตรง ซึ่งเป็นปรัชญาของ Go ที่ว่า "Don't communicate by sharing memory; share memory by communicating"
// Unbuffered Channel
ch := make(chan string)
go func() {
ch <- "Hello from goroutine!" // ส่งข้อมูลเข้า Channel
}()
msg := <-ch // รับข้อมูลจาก Channel
fmt.Println(msg)
// Buffered Channel — มี Buffer รองรับ
jobs := make(chan int, 100)
// ส่งงานเข้า Channel
for i := 1; i <= 5; i++ {
jobs <- i
}
close(jobs)
// รับงานจาก Channel
for job := range jobs {
fmt.Println("Processing job:", job)
}
// Select — รอหลาย Channel พร้อมกัน
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "one"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "two"
}()
select {
case msg1 := <-ch1:
fmt.Println("Received", msg1)
case msg2 := <-ch2:
fmt.Println("Received", msg2)
case <-time.After(3 * time.Second):
fmt.Println("Timeout!")
}
Error Handling ใน Go
Go ไม่มี try-catch แบบภาษาอื่น แต่ใช้การ Return Error เป็นค่าจากฟังก์ชัน ซึ่งบังคับให้ Developer จัดการ Error ทุกครั้ง
import (
"errors"
"fmt"
"os"
)
// Custom Error
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error: %s - %s", e.Field, e.Message)
}
// ฟังก์ชันที่ Return Error
func readFile(path string) ([]byte, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read %s: %w", path, err) // Wrap Error
}
return data, nil
}
func main() {
// ตรวจสอบ Error ทุกครั้ง
data, err := readFile("config.json")
if err != nil {
// ตรวจสอบประเภท Error
if errors.Is(err, os.ErrNotExist) {
fmt.Println("File not found")
} else {
fmt.Println("Error:", err)
}
return
}
fmt.Println(string(data))
// errors.As — ตรวจสอบ Custom Error Type
var valErr *ValidationError
if errors.As(err, &valErr) {
fmt.Printf("Field: %s, Message: %s\n", valErr.Field, valErr.Message)
}
}
Packages และ Modules
Go ใช้ระบบ Modules สำหรับจัดการ Dependencies ตั้งแต่ Go 1.11 เป็นต้นมา ทำให้จัดการ Package ได้ง่ายและมีประสิทธิภาพ
# สร้าง Module ใหม่
go mod init github.com/username/myproject
# เพิ่ม Dependency
go get github.com/gin-gonic/gin@latest
# อัพเดท Dependencies
go mod tidy
# ดู Dependencies ทั้งหมด
go list -m all
// โครงสร้างโปรเจกต์ที่ดี
// myproject/
// ├── go.mod
// ├── go.sum
// ├── main.go
// ├── internal/ ← Package ที่ใช้เฉพาะภายใน
// │ ├── handler/
// │ ├── service/
// │ └── repository/
// ├── pkg/ ← Package ที่ Share ได้
// │ └── utils/
// └── cmd/ ← Entry points
// └── server/
// └── main.go
Standard Library ที่สำคัญ
net/http — สร้าง HTTP Server
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func jsonHandler(w http.ResponseWriter, r *http.Request) {
data := map[string]interface{}{
"message": "success",
"status": 200,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(data)
}
func main() {
http.HandleFunc("/", helloHandler)
http.HandleFunc("/api/hello", jsonHandler)
fmt.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
encoding/json — ทำงานกับ JSON
type Product struct {
ID int `json:"id"`
Name string `json:"name"`
Price float64 `json:"price"`
InStock bool `json:"in_stock,omitempty"`
}
// Struct → JSON (Marshal)
product := Product{ID: 1, Name: "Laptop", Price: 25999.00, InStock: true}
jsonBytes, err := json.Marshal(product)
fmt.Println(string(jsonBytes))
// {"id":1,"name":"Laptop","price":25999,"in_stock":true}
// JSON → Struct (Unmarshal)
jsonStr := `{"id":2,"name":"Mouse","price":599}`
var p Product
json.Unmarshal([]byte(jsonStr), &p)
fmt.Println(p.Name) // Mouse
os — ทำงานกับ File System
import "os"
// อ่านไฟล์ทั้งหมด
data, err := os.ReadFile("config.txt")
// เขียนไฟล์
os.WriteFile("output.txt", []byte("Hello"), 0644)
// Environment Variables
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
// Command-line Arguments
args := os.Args[1:]
สร้าง REST API ด้วย Go
มาสร้าง REST API สำหรับจัดการ Todo List แบบ CRUD กัน ใช้ Standard Library net/http ล้วนๆ ไม่พึ่ง Framework ภายนอก เพื่อให้เข้าใจพื้นฐานก่อน
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"strings"
"sync"
)
type Todo struct {
ID int `json:"id"`
Title string `json:"title"`
Completed bool `json:"completed"`
}
var (
todos = []Todo{}
nextID = 1
mu sync.Mutex
)
func todosHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
switch r.Method {
case http.MethodGet:
// GET /todos — ดึงรายการทั้งหมด
mu.Lock()
json.NewEncoder(w).Encode(todos)
mu.Unlock()
case http.MethodPost:
// POST /todos — สร้างรายการใหม่
var todo Todo
if err := json.NewDecoder(r.Body).Decode(&todo); err != nil {
http.Error(w, "Invalid JSON", http.StatusBadRequest)
return
}
mu.Lock()
todo.ID = nextID
nextID++
todos = append(todos, todo)
mu.Unlock()
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(todo)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func todoHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
idStr := strings.TrimPrefix(r.URL.Path, "/todos/")
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "Invalid ID", http.StatusBadRequest)
return
}
mu.Lock()
defer mu.Unlock()
for i, todo := range todos {
if todo.ID == id {
switch r.Method {
case http.MethodGet:
json.NewEncoder(w).Encode(todo)
return
case http.MethodPut:
var updated Todo
json.NewDecoder(r.Body).Decode(&updated)
updated.ID = id
todos[i] = updated
json.NewEncoder(w).Encode(updated)
return
case http.MethodDelete:
todos = append(todos[:i], todos[i+1:]...)
w.WriteHeader(http.StatusNoContent)
return
}
}
}
http.Error(w, "Not found", http.StatusNotFound)
}
func main() {
http.HandleFunc("/todos", todosHandler)
http.HandleFunc("/todos/", todoHandler)
fmt.Println("API Server running on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Testing ใน Go
Go มี Testing Framework ในตัว ไม่ต้องติดตั้งเพิ่ม ชื่อไฟล์ Test ต้องลงท้ายด้วย _test.go และฟังก์ชัน Test ต้องขึ้นต้นด้วย Test
// math.go
package mathutil
func Add(a, b int) int {
return a + b
}
func Multiply(a, b int) int {
return a * b
}
// math_test.go
package mathutil
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Add(2,3) = %d; want 5", result)
}
}
// Table-driven tests (Go convention)
func TestMultiply(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 6},
{"zero", 5, 0, 0},
{"negative", -2, 3, -6},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Multiply(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Multiply(%d,%d) = %d; want %d",
tt.a, tt.b, result, tt.expected)
}
})
}
}
// Benchmark
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}
# รัน Tests
go test ./...
go test -v ./... # verbose
go test -run TestAdd # รันเฉพาะ test
go test -bench=. # รัน benchmarks
go test -cover # ดู coverage
go test -coverprofile=coverage.out && go tool cover -html=coverage.out
Go vs Node.js vs Python — เปรียบเทียบ
| คุณสมบัติ | Go | Node.js | Python |
|---|---|---|---|
| ประเภท | Compiled, Static | Interpreted, Dynamic | Interpreted, Dynamic |
| ความเร็ว | เร็วมาก | ปานกลาง | ช้า |
| Concurrency | Goroutines | Event Loop | Threading/asyncio |
| Learning Curve | ง่าย | ง่าย | ง่ายที่สุด |
| Memory Usage | ต่ำ | ปานกลาง | สูง |
| Deployment | Binary เดียว | ต้อง Node Runtime | ต้อง Python Runtime |
| Package Manager | go mod | npm/yarn | pip |
| เหมาะกับ | Backend, CLI, DevOps | Web, Real-time | AI/ML, Scripts, Web |
| Error Handling | Error Return | try-catch | try-except |
| Type System | Static + Generics | Dynamic (TS optional) | Dynamic (hints) |
Framework ยอดนิยมสำหรับ Go
Gin — เร็วที่สุด
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/api/users", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "list users"})
})
r.POST("/api/users", func(c *gin.Context) {
var user struct {
Name string `json:"name"`
Email string `json:"email"`
}
c.BindJSON(&user)
c.JSON(201, gin.H{"user": user})
})
r.Run(":8080")
}
Echo — สมดุลระหว่างฟีเจอร์และประสิทธิภาพ
package main
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
e.GET("/api/users", func(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{"message": "list users"})
})
e.Logger.Fatal(e.Start(":8080"))
}
Fiber — แรงบันดาลใจจาก Express.js
package main
import "github.com/gofiber/fiber/v2"
func main() {
app := fiber.New()
app.Get("/api/users", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"message": "list users"})
})
app.Listen(":8080")
}
Deployment ของ Go Application
Build สำหรับ Platform ต่างๆ
# Build สำหรับ Linux (จาก Windows/Mac)
GOOS=linux GOARCH=amd64 go build -o server main.go
# Build สำหรับ Windows
GOOS=windows GOARCH=amd64 go build -o server.exe main.go
# Build สำหรับ Mac (Apple Silicon)
GOOS=darwin GOARCH=arm64 go build -o server main.go
# Build แบบ Static (ไม่พึ่ง libc)
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o server main.go
Docker สำหรับ Go
# Dockerfile (Multi-stage build)
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o server .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]
Image ที่ได้จะมีขนาดเพียง 10-20MB เท่านั้น เทียบกับ Node.js image ที่มักจะ 200-500MB
Best Practices สำหรับ Go Developer
- ใช้ gofmt/goimports — Format Code ให้เป็นมาตรฐาน ไม่ต้องถกเถียงเรื่อง Style อีก
- จัดการ Error ทุกครั้ง — อย่าละเลย Error Return ใช้
fmt.Errorf("context: %w", err)เพื่อ Wrap Error ให้มี Context - ใช้ Interface ให้เล็ก — Interface ที่ดีมี 1-3 Method ดูตัวอย่างจาก
io.Readerที่มีแค่Read()Method เดียว - ตั้งชื่อ Package ให้สั้นและชัดเจน — ใช้ชื่อเดียว ไม่ใช่ under_score หรือ camelCase เช่น
http,json,user - เขียน Table-driven Tests — เป็น Convention ของ Go ที่ทำให้เพิ่ม Test Case ง่ายและอ่านง่าย
- ใช้ Context สำหรับ Cancellation — ส่ง
context.Contextเป็น Parameter แรกเสมอในฟังก์ชันที่อาจใช้เวลานาน - หลีกเลี่ยง Global State — ใช้ Dependency Injection แทน Global Variables
- ใช้ Goroutine + Channel อย่างระมัดระวัง — อย่าสร้าง Goroutine โดยไม่มีทางหยุด ใช้ Context กับ Done Channel เพื่อจัดการ Lifecycle
เครื่องมือที่ Go Developer ควรรู้จัก
| เครื่องมือ | หน้าที่ |
|---|---|
go fmt | Format Code |
go vet | ตรวจจับ Bug เบื้องต้น |
go test | รัน Tests |
go build | Build Binary |
go run | Compile + Run ทันที |
go mod tidy | จัดการ Dependencies |
golangci-lint | Linter รวมหลายตัว |
delve | Debugger สำหรับ Go |
gopls | Language Server (สำหรับ IDE) |
air | Live Reload สำหรับ Development |
สรุป
Go เป็นภาษาที่ออกแบบมาอย่างดีสำหรับการพัฒนา Backend และ Infrastructure ในยุคปัจจุบัน ด้วยความเรียบง่าย ความเร็ว และความสามารถด้าน Concurrency ที่โดดเด่น ทำให้ Go เป็นตัวเลือกยอดนิยมสำหรับ Microservices, API Server, CLI Tools และ Cloud Native Applications
สำหรับนักพัฒนาที่มีพื้นฐาน Python หรือ JavaScript มาก่อน การเรียน Go จะเปิดโลกใหม่ในด้าน System Programming และ Performance ที่ภาษา Dynamic ไม่สามารถให้ได้ เริ่มต้นด้วยการสร้าง REST API ง่ายๆ แล้วค่อยขยายไปสู่ Microservices และ Cloud Infrastructure ด้วย Go คุณจะพร้อมสำหรับตลาดงานปี 2026 ที่ต้องการ Backend Developer ที่เข้าใจทั้ง Performance และ Scalability
