提供地道 Go 语言模式与最佳实践,帮助构建健壮高效且易维护的应用
复制安装指令,让 AI 自动完成配置 · 推荐新手
请帮我安装 askskill 上的 "golang-patterns" 技能: 1. 下载 https://raw.githubusercontent.com/affaan-m/ECC/main/skills/golang-patterns/SKILL.md 2. 保存为 ~/.claude/skills/golang-patterns/SKILL.md 3. 装好后重载技能,告诉我可以用了
请用符合 Go 惯用法的方式,设计一个并发任务处理器示例:包含 worker pool、context 取消、错误传递与优雅关闭,并解释为什么这样设计。
一份符合 Go 最佳实践的并发示例代码,并附上关键设计说明。
这是我当前的 Go 项目目录与部分代码,请按照 Go 社区常见约定,建议更清晰的包结构、命名方式、接口边界与错误处理策略。
针对项目结构、命名和模块边界的重构建议,附示例目录与代码调整方向。
请审查这段 Go 代码,指出不符合 idiomatic Go 的地方,包括命名、错误处理、切片与 map 使用、接口设计和性能问题,并给出改进版本。
一份带问题清单的代码审查结果,以及更符合 Go 规范的改进代码。
Idiomatic Go patterns and best practices for building robust, efficient, and maintainable applications.
Go favors simplicity over cleverness. Code should be obvious and easy to read.
// Good: Clear and direct
func GetUser(id string) (*User, error) {
user, err := db.FindUser(id)
if err != nil {
return nil, fmt.Errorf("get user %s: %w", id, err)
}
return user, nil
}
// Bad: Overly clever
func GetUser(id string) (*User, error) {
return func() (*User, error) {
if u, e := db.FindUser(id); e == nil {
return u, nil
} else {
return nil, e
}
}()
}
Design types so their zero value is immediately usable without initialization.
// Good: Zero value is useful
type Counter struct {
mu sync.Mutex
count int // zero value is 0, ready to use
}
func (c *Counter) Inc() {
c.mu.Lock()
c.count++
c.mu.Unlock()
}
// Good: bytes.Buffer works with zero value
var buf bytes.Buffer
buf.WriteString("hello")
// Bad: Requires initialization
type BadCounter struct {
counts map[string]int // nil map will panic
}
Functions should accept interface parameters and return concrete types.
// Good: Accepts interface, returns concrete type
func ProcessData(r io.Reader) (*Result, error) {
data, err := io.ReadAll(r)
if err != nil {
return nil, err
}
return &Result{Data: data}, nil
}
// Bad: Returns interface (hides implementation details unnecessarily)
func ProcessData(r io.Reader) (io.Reader, error) {
// ...
}
// Good: Wrap errors with context
func LoadConfig(path string) (*Config, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("load config %s: %w", path, err)
}
var cfg Config
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("parse config %s: %w", path, err)
}
return &cfg, nil
}
// Define domain-specific errors
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation failed on %s: %s", e.Field, e.Message)
}
// Sentinel errors for common cases
var (
ErrNotFound = errors.New("resource not found")
ErrUnauthorized = errors.New("unauthorized")
ErrInvalidInput = errors.New("invalid input")
)
func HandleError(err error) {
// Check for specific error
if errors.Is(err, sql.ErrNoRows) {
log.Println("No records found")
return
}
// Check for error type
var validationErr *ValidationError
if errors.As(err, &validationErr) {
log.Printf("Validation error on field %s: %s",
validationErr.Field, validationErr.Message)
return
}
// Unknown error
log.Printf("Unexpected error: %v", err)
}
// Bad: Ignoring error with blank identifier
result, _ := doSomething()
// Good: Handle or explicitly document why it's safe to ignore
result, err := doSomething()
if err != nil {
return err
}
// Acceptable: When error truly doesn't matter (rare)
_ = writer.Close() // Best-effort cleanup, error logged elsewhere
func WorkerPool(jobs <-chan Job, results chan<- Result, numWorkers int) {
var wg sync.WaitGroup
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for job := range jobs {
results <- process(job)
}
}()
}
…
通过双评审智能体对结果进行对抗式校验,提升输出发布前的可靠性
提供地道 Kotlin 模式与最佳实践,帮助构建健壮高效且易维护的应用。