mcpField
G
golang-style

golang-style

github.com/fredrikaverpil开发25964 次安装2 天前更新
代码仓库

关于 golang-style

golang-style 是一组 Go 编码规范,供编写 Go 代码时遵循。内容涵盖错误处理、命名、注释、代码结构和文档查询等约定。

主要功能

  1. 01遵循 Go 语言箴言与惯例
  2. 02错误添加上下文并妥善处理
  3. 03避免变量名遮蔽预声明标识符
  4. 04规定注释与代码行长度
  5. 05使用 go doc 查询文档

适用场景

  1. 01统一 Go 项目的代码风格
  2. 02编写带上下文的错误处理
  3. 03检查 Go 代码命名和注释

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/fredrikaverpil/dotfiles --skill golang-style

安装后在 Claude Code 中输入/golang-style确认已加载。

详细介绍

Go 编码约定

格言

尽量遵循以下格言:

Go 格言 简洁、优美、精炼 不要通过共享内存来通信,而要通过通信来共享内存。 并发不等于并行。 通道负责协调;互斥锁负责串行化。 接口越大,抽象越弱。 让零值发挥作用。 interface{} 什么也说明不了。 gofmt 的风格不是任何人的最爱,但 gofmt 是所有人的最爱。 少量复制胜过少量依赖。 系统调用必须始终由构建标签保护。 Cgo 必须始终由构建标签保护。 Cgo 不是 Go。 使用 unsafe 包就没有任何保证。 清晰胜过巧妙。 反射永远不清晰。 错误是值。 不要只检查错误,还要妥善处理错误。 设计架构,命名组件,记录细节。 文档是写给用户的。 不要 panic。

编写 Go 代码时,严格遵循这些约定。

顺畅路径编码

组织代码,让成功路径直截了当地向下执行。立即处理错误,然后继续 主要逻辑。

// Correct: happy path flows down.
func ProcessUser(id string) (*User, error) {
    user, err := db.GetUser(id)
    if err != nil {
        return nil, fmt.Errorf("get user %s: %w", id, err)
    }

    if err := user.Validate(); err != nil {
        return nil, fmt.Errorf("validate user %s: %w", id, err)
    }

    return user, nil
}

// Wrong: main logic nested inside conditions.
func ProcessUser(id string) (*User, error) {
    user, err := db.GetUser(id)
    if err == nil {
        if err := user.Validate(); err == nil {
            return user, nil
        } else {
            return nil, err
        }
    }
    return nil, err
}

错误包装

始终使用 %w 包装错误并提供上下文。包含操作及相关标识符。

// Correct: wrapped with context.
if err != nil {
    return fmt.Errorf("create order for customer %s: %w", customerID, err)
}

// Wrong: no context.
if err != nil {
    return err
}

哨兵错误

为预期的错误情况定义包级哨兵错误。使用 errors.Is() 进行检查。

// Define at package level.
var (
    ErrNotFound     = errors.New("not found")
    ErrUnauthorized = errors.New("unauthorized")
    ErrInvalidInput = errors.New("invalid input")
)

// Return sentinel errors.
func GetUser(id string) (*User, error) {
    user := db.Find(id)
    if user == nil {
        return nil, ErrNotFound
    }
    return user, nil
}

// Check with errors.Is().
user, err := GetUser(id)
if errors.Is(err, ErrNotFound) {
    // Handle not found case.
}

注释

所有注释都以句号结尾。

// ProcessOrder handles order creation and validation.
func ProcessOrder(o *Order) error {
    // Validate the order before processing.
    if err := o.Validate(); err != nil {
        return err
    }
    // Continue with order processing.
    return nil
}

命名约定

切勿将 Go 的预声明标识符用作变量或参数名。这些标识符包括可以被遮蔽、但不应被遮蔽的内置函数和常量。

// Wrong: shadows built-in identifiers.
func process(new string, len int, make bool) error {
    copy := "data"
    return nil
}

// Correct: use descriptive names instead.
func process(name string, length int, shouldCreate bool) error {
    dataCopy := "data"
    return nil
}

应避免使用的预声明标识符:

  • 函数:new、make、len、cap、append、copy、delete、close、 panic、recover、print、println、complex、real、imag、clear、 min、max
  • 常量:true、false、iota、nil
  • 类型:error、bool、string、int、int8、int16、int32、int64、 uint、uint8、uint16、uint32、uint64、uintptr、float32、 float64、complex64、complex128、byte、rune、any、comparable

行长度

行长最多为 120 个字符。在合理的位置拆分长行。

// Correct: break at logical points.
func ProcessOrderWithValidation(
    ctx context.Context,
    order *Order,
    validator OrderValidator,
) (*Result, error) {
    return nil, fmt.Errorf(
        "process order %s for customer %s: %w",
        order.ID,
        order.CustomerID,
        err,
    )
}

查阅文档

使用 go doc 查阅标准库和软件包的文档:

go doc fmt.Errorf
go doc errors.Is
go doc context

Einride

如果项目隶属于 Einride 组织,始终使用项目中的 Makefile,这些文件由 Sage(.sage 文件夹)生成。

评论

支持 Markdown