G

golang-code-style

by @samberv
4.6(20)

Go代码风格规范,关注需要人工判断的清晰度规则,与linter配合保障代码质量

golangcode-stylecode-reviewbest-practicesbackend-developmentGitHub
安装方式
npx skills add https://github.com/samber/cc-skills-golang --skill golang-code-style
compare_arrows

Before / After 效果对比

1
使用前

团队开发Go代码时,命名、注释、结构组织风格不一,代码审查时反复讨论风格问题,影响开发效率

使用后

提供统一的Go代码风格规范,自动检查命名和清晰度问题,与linter互补,减少代码审查中的风格争议

SKILL.md

golang-code-style

Community default. A company skill that explicitly supersedes samber/cc-skills-golang@golang-code-style skill takes precedence.

Go Code Style

Style rules that require human judgment — linters handle formatting, this skill handles clarity. For naming see samber/cc-skills-golang@golang-naming skill; for design patterns see samber/cc-skills-golang@golang-design-patterns skill; for struct/interface design see samber/cc-skills-golang@golang-structs-interfaces skill.

"Clear is better than clever." — Go Proverbs

When ignoring a rule, add a comment to the code.

Line Length & Breaking

No rigid line limit, but lines beyond ~120 characters MUST be broken. Break at semantic boundaries, not arbitrary column counts. Function calls with 4+ arguments MUST use one argument per line — even when the prompt asks for single-line code:

// Good — each argument on its own line, closing paren separate
mux.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
    handleUsers(
        w,
        r,
        serviceName,
        cfg,
        logger,
        authMiddleware,
    )
})

When a function signature is too long, the real fix is often fewer parameters (use an options struct) rather than better line wrapping. For multi-line signatures, put each parameter on its own line.

Variable Declarations

SHOULD use := for non-zero values, var for zero-value initialization. The form signals intent: var means "this starts at zero."

var count int              // zero value, set later
name := "default"          // non-zero, := is appropriate
var buf bytes.Buffer       // zero value is ready to use

Slice & Map Initialization

Slices and maps MUST be initialized explicitly, never nil. Nil maps panic on write; nil slices serialize to null in JSON (vs [] for empty slices), surprising API consumers.

users := []User{}                       // always initialized
m := map[string]int{}                   // always initialized
users := make([]User, 0, len(ids))      // preallocate when capacity is known
m := make(map[string]int, len(items))   // preallocate when size is known

Do not preallocate speculatively — make([]T, 0, 1000) wastes memory when the common case is 10 items.

Composite Literals

Composite literals MUST use field names — positional fields break when the type adds or reorders fields:

srv := &http.Server{
    Addr:         ":8080",
    ReadTimeout:  5 * time.Second,
    WriteTimeout: 10 * time.Second,
}

Control Flow

Reduce Nesting

Errors and edge cases MUST be handled first (early return). Keep the happy path at minimal indentation:

func process(data []byte) (*Result, error) {
    if len(data) == 0 {
        return nil, errors.New("empty data")
    }

    parsed, err := parse(data)
    if err != nil {
        return nil, fmt.Errorf("parsing: %w", err)
    }

    return transform(parsed), nil
}

Eliminate Unnecessary else

When the if body ends with return/break/continue, the else MUST be dropped. Use default-then-override for simple assignments — assign a default, then override with independent conditions or a switch:

// Good — default-then-override with switch (cleanest for mutually exclusive overrides)
level := slog.LevelInfo
switch {
case debug:
    level = slog.LevelDebug
case verbose:
    level = slog.LevelWarn
}

// Bad — else-if chain hides that there's a default
if debug {
    level = slog.LevelDebug
} else if verbose {
    level = slog.LevelWarn
} else {
    level = slog.LevelInfo
}

Complex Conditions & Init Scope

When an if condition has 3+ operands, MUST extract into named booleans — a wall of || is unreadable and hides business logic. Keep expensive checks inline for short-circuit benefit. Details

// Good — named booleans make intent clear
isAdmin := user.Role == RoleAdmin
isOwner := resource.OwnerID == user.ID
isPublicVerified := resource.IsPublic && user.IsVerified
if isAdmin || isOwner || isPublicVerified || permissions.Contains(PermOverride) {
    allow()
}

Scope variables to if blocks when only needed for the check:

if err := validate(input); err != nil {
    return err
}

Switch Over If-Else Chains

When comparing the same variable multiple times, prefer switch:

switch status {
case StatusActive:
    activate()
case StatusInactive:
    deactivate()
default:
    panic(fmt.Sprintf("unexpected status: %d", status))
}

Function Design

  • Functions SHOULD be short and focused — one function, one job.

  • Functions SHOULD have ≤4 parameters. Beyond that, use an options struct (see samber/cc-skills-golang@golang-design-patterns skill).

  • Parameter order: context.Context first, then inputs, then output destinations.

  • Naked returns help in very short functions (1-3 lines) where return values are obvious, but become confusing when readers must scroll to find what's returned — name returns explicitly in longer functions.

func FetchUser(ctx context.Context, id string) (*User, error)
func SendEmail(ctx context.Context, msg EmailMessage) error  // grouped into struct

Prefer range for Iteration

SHOULD use range over index-based loops. Use range n (Go 1.22+) for simple counting.

for _, user := range users {
    process(user)
}

Value vs Pointer Arguments

Pass small types (string, int, bool, time.Time) by value. Use pointers when mutating, for large structs (~128+ bytes), or when nil is meaningful. Details

Code Organization Within Files

  • Group related declarations: type, constructor, methods together

  • Order: package doc, imports, constants, types, constructors, methods, helpers

  • One primary type per file when it has significant methods

  • Blank imports (_ "pkg") register side effects (init functions). Restricting them to main and test packages makes side effects visible at the application root, not hidden in library code

  • Dot imports pollute the namespace and make it impossible to tell where a name comes from — never use in library code

  • Unexport aggressively — you can always export later; unexporting is a breaking change

String Handling

Use strconv for simple conversions (faster), fmt.Sprintf for complex formatting. Use %q in error messages to make string boundaries visible. Use strings.Builder for loops, + for simple concatenation.

Type Conversions

Prefer explicit, narrow conversions. Use generics over any when a concrete type will do:

func Contains[T comparable](slice []T, target T) bool  // not []any

Philosophy

  • "A little copying is better than a little dependency"

  • Use slices and maps standard packages; for filter/group-by/chunk, use github.com/samber/lo

  • "Reflection is never clear" — avoid reflect unless necessary

  • Don't abstract prematurely — extract when the pattern is stable

  • Minimize public surface — every exported name is a commitment

Parallelizing Code Style Reviews

When reviewing code style across a large codebase, use up to 5 parallel sub-agents (via the Agent tool), each targeting an independent style concern (e.g. control flow, function design, variable declarations, string handling, code organization).

Enforce with Linters

Many rules are enforced automatically: gofmt, gofumpt, goimports, gocritic, revive, wsl_v5. → See the samber/cc-skills-golang@golang-linter skill.

Cross-References

  • → See the samber/cc-skills-golang@golang-naming skill for identifier naming conventions

  • → See the samber/cc-skills-golang@golang-structs-interfaces skill for pointer vs value receivers, interface design

  • → See the samber/cc-skills-golang@golang-design-patterns skill for functional options, builders, constructors

  • → See the samber/cc-skills-golang@golang-linter skill for automated formatting enforcement

Weekly Installs801Repositorysamber/cc-skills-golangGitHub Stars1.1KFirst SeenMar 22, 2026Security AuditsGen Agent Trust HubPassSocketPassSnykPassInstalled onopencode760cursor754codex749gemini-cli747github-copilot746amp745

用户评价 (0)

发表评价

效果
易用性
文档
兼容性

暂无评价

统计数据

安装量33.9K
评分4.6 / 5.0
版本
更新日期2026年7月9日
对比案例1 组

用户评分

4.6(20)
5
75%
4
25%
3
0%
2
0%
1
0%

为此 Skill 评分

0.0

兼容平台

🔧Claude Code

时间线

创建2026年4月9日
最后更新2026年7月9日
🎁 Agent 知识卡片
调研问卷