$ loading_
提供惯用Go设计模式与最佳实践,帮助构建稳健高效且易维护的应用
复制安装指令,让 AI 自动完成配置 · 推荐新手
请帮我安装 askskill 上的 "golang-patterns" 技能: 1. 下载 https://raw.githubusercontent.com/affaan-m/ECC/main/docs/ja-JP/skills/golang-patterns/SKILL.md 2. 保存为 ~/.claude/skills/golang-patterns/SKILL.md 3. 装好后重载技能,告诉我可以用了
请根据惯用Go实践,评审下面的项目目录与模块划分,并提出重构建议,包括包职责、接口设计、错误处理、依赖注入和可测试性改进。
给出符合Go约定的项目结构优化建议,以及可执行的重构步骤清单。
我正在用Go处理高并发任务队列,请推荐适合的并发模式,并说明何时使用goroutine、channel、worker pool、context取消和超时控制。
输出针对场景的并发方案建议、模式对比,以及示例实现思路。
请检查这段Go代码是否符合最佳实践,并从命名、错误处理、接口抽象、日志、测试策略和性能角度提出改进意见。
返回结构化代码审查意见,并附上更符合Go风格的修改建议。
堅牢で効率的かつ保守可能なアプリケーションを構築するための慣用的なGoパターンとベストプラクティス。
Goは巧妙さよりもシンプルさを好みます。コードは明白で読みやすいものであるべきです。
// 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
}
}()
}
型を設計する際、そのゼロ値が初期化なしですぐに使用できるようにします。
// 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
}
関数はインターフェースパラメータを受け取り、具体的な型を返すべきです。
// 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)
}
}()
}
wg.Wait()
close(results)
}
func FetchWithTimeout(ctx context.Context, url string) ([]byte, error) {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
…
通过双评审智能体对结果进行对抗式校验,提升输出发布前的可靠性
提供惯用 Kotlin 模式与最佳实践,帮助构建稳健高效且易维护的应用