
Go 1.23 phát hành tháng 8/2024 mang đến nhiều cải tiến quan trọng: iterators, telemetry, toolchain directives, và nhiều thay đổi trong standard library. Bài viết này tổng hợp những điều mới nhất và best practices hiện đại để viết Go code an toàn, hiệu năng, và dễ bảo trì.
Iterators (Range over function) — Go 1.23 feature mới
Go 1.23 giới thiệu range over function — cho phép for range lặp qua các function iterator thay vì chỉ slice/map/channel. Đây là thay đổi lớn nhất trong syntax kể từ generics (Go 1.18).
func AllItems() iter.Seq[int] {
return func(yield func(int) bool) {
for i := 0; i < 10; i++ {
if !yield(i) {
return
}
}
}
}
func main() {
for item := range AllItems() {
fmt.Println(item)
}
}
Iterator trả về `iter.Seq[T]` (chỉ yield value) hoặc `iter.Seq2[K, V]` (yield key, value). Package `iter` cung cấp helper như `iter.Backwards`, `iter.Enumerate`, `iter.Filter`.

Best practices cho iterator:
- Luôn kiểm tra return của `yield` để hỗ trợ early break
- Dùng `iter.Seq` thay vì closure tùy chỉnh cho code rõ ràng
- Tránh allocation trong iterator hot path — reuse buffer khi có thể
- Iterator nên pure (không side effect) để dễ test và compose
Telemetry và Go toolchain directives
Go 1.23 tích hợp telemetry mặc định (có thể tắt qua `GOTELEMETRY=off`). Dữ liệu thu thập bao gồm: version Go, OS/arch, build time, lỗi compiler — KHÔNG thu thập source code.
Toolchain directive trong `go.mod`:
go 1.23
toolchain go1.23.0
Directive này ép Go sử dụng toolchain version cụ thể, tránh mismatch giữa CI và local. Kết hợp với `go env GOVERSION` để verify.

Standard library mới và cập nhật
Unique package (`unique.Make`, `unique.Handle`): Interning giá trị để giảm bộ nhớ và so sánh bằng pointer equality. Hữu ích cho string interning, enum-like values.
import "unique"
handle := unique.Make("some-long-string-key")
// So sánh O(1) bằng pointer
if handle == unique.Make("some-long-string-key") { ... }
Sync.Map.LoadOrStore trả về `(value, loaded bool)` — thay vì panic khi key chưa tồn tại.
Testing improvements: `testing.T.Setenv`, `testing.T.Chdir` an toàn cho parallel tests; `testing.B.Loop` cho benchmark chuẩn xác hơn.
Error handling hiện đại: fmt.Errorf với %w và errors.Is/As
Go 1.13 giới thiệu error wrapping với `%w`. Go 1.23 tiếp tục khuyến khích pattern này:
var ErrNotFound = errors.New("not found")
func FindUser(id string) (*User, error) {
user, err := db.Get(id)
if err != nil {
return nil, fmt.Errorf("find user %s: %w", id, err)
}
return user, nil
}
// Caller
if errors.Is(err, ErrNotFound) { ... }
var target *MyError
if errors.As(err, &target) { ... }
Best practice: Luôn wrap error với context (`%w`), tránh `fmt.Errorf(“%v”, err)` làm mất chain. Dùng sentinel error (`var ErrX = errors.New(…)`) cho error domain cụ thể.
Concurrency: Structured concurrency với errgroup
Package `golang.org/x/sync/errgroup` cung cấp structured concurrency — quản lý goroutine group, cancel tự động khi có lỗi:
g, ctx := errgroup.WithContext(ctx)
g.Go(func() error {
return fetchUsers(ctx)
})
g.Go(func() error {
return fetchPosts(ctx)
})
if err := g.Wait(); err != nil {
log.Printf("failed: %v", err)
}

Kết hợp với `context.WithTimeout` để tránh goroutine leak. Luôn dùng `errgroup` thay vì `sync.WaitGroup` raw cho error handling an toàn.
Performance: Profile-guided optimization (PGO)
Go 1.21+ hỗ trợ PGO (Profile-Guided Optimization). Bật bằng `go build -pgo=auto` — compiler tự dùng profile từ `default.pgo` (tạo bằng `go test -cpuprofile`). PGO thường cải thiện 2-7% throughput, đôi khi lên 10-15% cho hot path.
Best practices PGO:
- Collect profile dưới production load thực tế (không phải benchmark)
- Commit `default.pgo` vào repo để CI dùng
- Rebuild định kỳ khi code thay đổi lớn
- Kết hợp với `-trimpath` và `-ldflags=-s -w` cho binary nhỏ hơn
Security: GODEBUG và supply chain
Go 1.23 tăng cường supply chain security:
- GODEBUG=httpresponseheaders=false tắt header response body logging (CVE-2024-xxxx mitigation)
- go vet cảnh báo `G114` (Use of net/http client without timeout)
- go mod download -verify kiểm tra checksum trước khi build
- go install -mod=mod cài đặt trong module mode, tránh GOPATH pollution
Luôn set timeout cho HTTP client:
client := &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
},
}
Testing và observability: slog, metric, trace
Standard library `log/slog` (Go 1.21+) là logging chuẩn cho production:
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
logger.Info("request received", "method", r.Method, "path", r.URL.Path, "duration_ms", elapsed.Milliseconds())
Kết hợp với `expvar` (metrics) và `runtime/trace` (distributed tracing). Go 1.23 cải thiện `runtime/trace` format — dùng `go tool trace` để phân tích goroutine contention, GC pause.
Modules và dependency management
Go 1.23 tiếp tục cải thiện module graph pruning (lazy loading). Best practices:
- Luôn commit `go.sum` vào repo
- Dùng `go mod tidy -go=1.23` để dọn dependency không dùng
- Pin dependency version trong `go.mod` (tránh `latest`)
- Audit supply chain: `go list -m -json all | nancy sleuth` (check CVE)
- Vendor cho production: `go mod vendor` + `go build -mod=vendor`
Kết luận
Go 1.23 là bản phát hành quan trọng: iterators thay đổi cách viết code lặp, telemetry cung cấp visibility, unique package giải quyết memory overhead. Các best practices cốt lõi vẫn giữ nguyên: code đơn giản, error wrapping rõ ràng, structured concurrency, và profiling thường xuyên. Developer Việt Nam nên nâng cấp toolchain sớm để tận dụng PGO và security fixes, đồng thời adopt slog cho observability chuẩn.
Tham khảo thêm: Go 1.23 Release Notes, Range over function proposal, errgroup documentation, PGO guide.
