go – skill Lập trình cho agent AI
Hướng dẫn code siêu chuẩn theo ngôn ngữ dành riêng cho Go.
Cài skill go bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/go-d9665.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /go – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/go-d9665.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $go – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/go-d9665.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /go – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/go-d9665.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /go – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
Go: Idiomatic Efficiency Reference
Apply only within the requested scope and current project conventions. Preserve behavior, ownership, error handling, accessibility and security; examples are independent fragments, not equivalent rewrites in every context. Verify language/library versions and run relevant checks. Required tests and user-facing progress/results take precedence over brevity rules. Do not install dependencies or delete files merely to follow these examples.
When to Use
- Use this skill when the task matches this description: Language-specific super-code guidelines for go.
Table of Contents
1. [Error Handling](#errors)
2. [Slices & Maps](#slices)
3. [Goroutines & Channels](#concurrency)
4. [Structs & Interfaces](#structs)
5. [Functions & Closures](#functions)
6. [Anti-patterns specific to Go](#antipatterns)
---
1. Error Handling {#errors}
// ❌ Ignoring errors
result, _ := os.Open(path)
// ✅ — always handle; only use _ when error is provably irrelevant
result, err := os.Open(path)
if err != nil {
return fmt.Errorf("open %s: %w", path, err)
}// ❌ Redundant error variable
err := doA()
if err != nil { return err }
err = doB()
if err != nil { return err }
// ✅ — each :=/: is fine; this is idiomatic Go. Don't try to "fix" it.
// What you CAN simplify: collapsing to one-liners where the if body is a single return
if err := doA(); err != nil { return err }
if err := doB(); err != nil { return err }// ❌ Custom error type with no added value
type MyError struct{ msg string }
func (e MyError) Error() string { return e.msg }
// ✅ — use errors.New or fmt.Errorf unless callers need to inspect type
var ErrNotFound = errors.New("not found")
return fmt.Errorf("lookup %q: %w", key, ErrNotFound)Wrap errors with %w (not %v) so callers can use errors.Is / errors.As.
---
2. Slices & Maps {#slices}
// ❌ Growing a slice without pre-allocation when size is known
var result []string
for _, item := range items {
result = append(result, item.Name)
}
// ✅
result := make([]string, 0, len(items))
for _, item := range items {
result = append(result, item.Name)
}// ❌ Manual existence check before map write
if _, ok := m[key]; !ok {
m[key] = []string{}
}
m[key] = append(m[key], value)
// ✅ — append to nil slice is valid Go
m[key] = append(m[key], value)// ❌ Copying a map by assignment (copies reference)
copy := original
// ✅
copy := make(map[K]V, len(original))
for k, v := range original { copy[k] = v }---
3. Goroutines & Channels {#concurrency}
// ❌ Fire-and-forget goroutine with no lifecycle
go doWork()
// ✅ — use errgroup or WaitGroup to track completion
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
doWork()
}()
wg.Wait()// ❌ Unbuffered channel causing unnecessary goroutine block
ch := make(chan Result)
go func() { ch <- compute() }()
result := <-ch
// ✅ — for single-result, buffered channel avoids goroutine leak if receiver exits early
ch := make(chan Result, 1)
go func() { ch <- compute() }()
result := <-ch// ❌ select with a busy-wait default
for {
select {
case v := <-ch:
process(v)
default:
// spin
}
}
// ✅ — blocking select unless you genuinely need non-blocking
for v := range ch {
process(v)
}Use golang.org/x/sync/errgroup for fan-out with error collection.
---
4. Structs & Interfaces {#structs}
// ❌ Large interface
type Storage interface {
Get(key string) ([]byte, error)
Set(key string, val []byte) error
Delete(key string) error
List(prefix string) ([]string, error)
// ... 10 more methods
}
// ✅ — small, composable interfaces
type Getter interface { Get(key string) ([]byte, error) }
type Setter interface { Set(key string, val []byte) error }
type Storage interface { Getter; Setter }// ❌ Returning concrete struct from constructor (ties callers to implementation)
func NewStore() *RedisStore { ... }
// Returning a concrete type is idiomatic; define small interfaces at consumers.
// Return an interface only when the API deliberately promises that abstraction.
func NewStore() Storage { return &RedisStore{...} }// ❌ Pointer receiver for tiny value types
func (p *Point) X() float64 { return p.x }
// ✅ — value receiver for small immutable types
func (p Point) X() float64 { return p.x }Rule: pointer receiver when method mutates state OR struct is large (>3 fields of non-trivial size). Value receiver otherwise.
---
5. Functions & Closures {#functions}
// ❌ Named return values used just to avoid a variable declaration
func divide(a, b float64) (result float64, err error) {
result = a / b
return
}
// ✅ — named returns are worth it only for deferred mutation or documentation
func divide(a, b float64) (float64, error) {
if b == 0 { return 0, errors.New("division by zero") }
return a / b, nil
}// ❌ Closure capturing loop variable (classic Go bug, fixed in Go 1.22+)
// Pre-1.22: each goroutine captures the same i
for i := 0; i < n; i++ {
go func() { use(i) }()
}
// ✅ (Go <1.22 — pass as parameter)
for i := 0; i < n; i++ {
go func(i int) { use(i) }(i)
}
// Go 1.22+: loop variable scoped per iteration, so the original is safe---
6. Anti-patterns specific to Go {#antipatterns}
| Anti-pattern | Preferred |
|---|---|
| if err != nil { return err } repeated 5+ times | acceptable — it's idiomatic Go |
| panic for expected errors | return err |
| init() with side effects | explicit initialization in main or constructors |
| interface{} / any without generics | use generics (Go 1.18+) or typed interfaces |
| Mutex field not adjacent to the data it protects | put mu directly above the field it guards |
| Channel of channels | usually a sign of over-engineering; redesign |
| time.Sleep in tests | use testing hooks or channels for synchronization |
| Exported types with unexported fields (when fields are the whole point) | record-style structs with all-exported fields |
| log.Fatal outside main | return errors up the stack |
Limitations
- These are language-specific guidelines and do not cover overall architectural decisions.
- Over-compression might reduce readability; apply judgement.
Skill liên quan
- go-concurrency-patterns – Làm chủ lập trình đồng thời trong Go với goroutines, channels, sync primitives và…
- go-rust-reverse – Dịch ngược binary Go và Rust đã bị strip: nhận diện runtime, khôi phục metadata…
- golang-pro – Làm chủ Go 1.21+ với các mẫu hiện đại, concurrency nâng cao, tối ưu hiệu năng và…
- google-no-code – Thiết kế Google Forms và kết nối trigger Apps Script (onFormSubmit) để gửi cảnh báo…
- graphql-schema – Các mẫu truy vấn, mutation và sinh code GraphQL. Dùng khi tạo thao tác GraphQL, làm việc…
- grok-delegate – Chỉ giao tác vụ lập trình cho Grok Build CLI khi người dùng yêu cầu rõ ràng, trong khi…
- grpc-golang – Xây dựng dịch vụ gRPC sẵn sàng production trong Go với mTLS, streaming và observability…
- hasdata-cli – Truy cập qua dòng lệnh để tìm kiếm, thu thập dữ liệu web và lấy dữ liệu có cấu trúc.