go

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

What I do

我的功能

I help you write Go code that follows professional style guide conventions based on Google's Go Style Guide. This includes:
  • Enforcing naming conventions (MixedCaps, mixedCaps)
  • Applying proper documentation and commentary
  • Managing imports correctly (grouping, ordering, renaming)
  • Following formatting rules (gofmt compliant)
  • Implementing error handling patterns
  • Writing clear, simple, and maintainable code
  • Applying concurrency best practices
  • Structuring packages effectively
我帮助你编写符合基于Google Go风格指南的专业规范的Go代码。这包括:
  • 强制执行命名规范(MixedCaps、mixedCaps)
  • 应用正确的文档与注释规范
  • 正确管理导入(分组、排序、重命名)
  • 遵循格式化规则(符合gofmt规范)
  • 实现错误处理模式
  • 编写清晰、简洁且可维护的代码
  • 应用并发最佳实践
  • 高效组织包结构

When to use me

适用场景

Use this skill when:
  • Writing new Go code that should follow style guide conventions
  • Refactoring existing Go code to match best practices
  • Reviewing Go code for style compliance
  • Adding documentation to Go packages, functions, or types
  • Organizing imports in Go files
  • Designing APIs and interfaces
  • Handling errors appropriately
在以下场景使用本技能:
  • 编写需要遵循风格指南规范的新Go代码
  • 重构现有Go代码以匹配最佳实践
  • 检查Go代码的风格合规性
  • 为Go包、函数或类型添加文档
  • 整理Go文件中的导入
  • 设计API与接口
  • 正确处理错误

Style Principles

风格原则

Go style follows these core principles in order of importance:
  1. Clarity - The code's purpose and rationale is clear to the reader
  2. Simplicity - The code accomplishes its goal in the simplest way possible
  3. Concision - The code has a high signal-to-noise ratio
  4. Maintainability - The code can be easily maintained
  5. Consistency - The code is consistent with the broader codebase
Go风格遵循以下核心原则,按重要性排序:
  1. 清晰性 - 代码的用途和设计思路对读者而言清晰易懂
  2. 简洁性 - 代码以最简单的方式实现目标
  3. 简洁性 - 代码具有高信噪比
  4. 可维护性 - 代码易于维护
  5. 一致性 - 代码与更广泛的代码库保持一致

Key style rules I enforce

我强制执行的关键风格规则

Formatting

格式化

All Go source files must conform to
gofmt
output:
bash
gofmt -w .
  • No fixed line length (prefer refactoring over splitting)
  • Use
    MixedCaps
    or
    mixedCaps
    (never snake_case)
  • Let the code speak for itself when possible
所有Go源文件必须符合
gofmt
的输出格式:
bash
gofmt -w .
  • 没有固定行长度(优先重构而非拆分)
  • 使用
    MixedCaps
    mixedCaps
    (绝不使用snake_case)
  • 尽可能让代码自我说明

Naming Conventions

命名规范

Packages:
go
// Good
package creditcard
package tabwriter
package oauth2

// Bad
package credit_card
package tabWriter
package oAuth2
Functions and Methods:
go
// Good - avoid repetition with package name
package yamlconfig
func Parse(input string) (*Config, error)

// Bad - repetitive
func ParseYAMLConfig(input string) (*Config, error)
Variables:
  • Short names in small scopes:
    i
    ,
    c
    ,
    db
  • Longer names in larger scopes:
    userCount
    ,
    databaseConnection
  • Avoid type in name:
    users
    not
    userSlice
Constants:
go
// Good
const MaxPacketSize = 512
const ExecuteBit = 1 << iota

// Bad
const MAX_PACKET_SIZE = 512
const kMaxBufferSize = 1024
Initialisms: Keep same case throughout:
go
// Good
func ServeHTTP(w http.ResponseWriter, r *http.Request)
func ProcessXMLAPI() error
var userID string

// Bad
func ServeHttp()
func ProcessXmlApi()
var userId string
Receiver Names:
  • Short (1-2 letters)
  • Abbreviation of type
  • Consistent across methods
go
// Good
func (c *Client) Get(url string) (*Response, error)
func (c *Client) Post(url string, body io.Reader) (*Response, error)

// Bad
func (client *Client) Get(url string) (*Response, error)
func (this *Client) Post(url string, body io.Reader) (*Response, error)
:
go
// Good
package creditcard
package tabwriter
package oauth2

// Bad
package credit_card
package tabWriter
package oAuth2
函数与方法:
go
// Good - 避免与包名重复
package yamlconfig
func Parse(input string) (*Config, error)

// Bad - 重复冗余
func ParseYAMLConfig(input string) (*Config, error)
变量:
  • 小作用域使用短名称:
    i
    c
    db
  • 大作用域使用长名称:
    userCount
    databaseConnection
  • 避免在名称中包含类型:使用
    users
    而非
    userSlice
常量:
go
// Good
const MaxPacketSize = 512
const ExecuteBit = 1 << iota

// Bad
const MAX_PACKET_SIZE = 512
const kMaxBufferSize = 1024
首字母缩写词: 全程保持相同大小写:
go
// Good
func ServeHTTP(w http.ResponseWriter, r *http.Request)
func ProcessXMLAPI() error
var userID string

// Bad
func ServeHttp()
func ProcessXmlApi()
var userId string
接收者名称:
  • 简短(1-2个字母)
  • 类型的缩写
  • 在所有方法中保持一致
go
// Good
func (c *Client) Get(url string) (*Response, error)
func (c *Client) Post(url string, body io.Reader) (*Response, error)

// Bad
func (client *Client) Get(url string) (*Response, error)
func (this *Client) Post(url string, body io.Reader) (*Response, error)

Documentation

文档

Package Comments:
go
// Package math provides basic constants and mathematical functions.
//
// This package does not guarantee bit-identical results across architectures.
package math
Function Comments:
go
// Good - complete sentence starting with function name
// Join concatenates the elements of its first argument to create a single string.
// The separator string sep is placed between elements in the resulting string.
func Join(elems []string, sep string) string

// Bad
// This function joins strings
func Join(elems []string, sep string) string
Comment Sentences:
  • Complete sentences for doc comments
  • Capitalize and punctuate properly
  • Start with the name being described
包注释:
go
// Package math provides basic constants and mathematical functions.
//
// This package does not guarantee bit-identical results across architectures.
package math
函数注释:
go
// Good - 完整句子,以函数名开头
// Join concatenates the elements of its first argument to create a single string.
// The separator string sep is placed between elements in the resulting string.
func Join(elems []string, sep string) string

// Bad
// This function joins strings
func Join(elems []string, sep string) string
注释句子:
  • 文档注释使用完整句子
  • 正确大写和标点
  • 以被描述的名称开头

Imports

导入

Import Grouping (separated by blank lines):
  1. Standard library packages
  2. Other (project and vendored) packages
  3. Protocol Buffer imports
  4. Side-effect imports
go
// Good
package main

import (
    "fmt"
    "hash/adler32"
    "os"

    "github.com/dsnet/compress/flate"
    "golang.org/x/text/encoding"

    foopb "myproj/foo/proto/proto"

    _ "myproj/rpc/protocols/dial"
)
Import Renaming:
go
// Good - clear and descriptive
import (
    foogrpc "path/to/package/foo_service_go_grpc"
    foopb "path/to/package/foo_service_go_proto"
)

// Avoid - unless necessary
import (
    foo "some/really/long/package/path"
)
Never use import dot (except in tests):
go
// Bad
import . "foo"

// Good
import "foo"
导入分组(用空行分隔):
  1. 标准库包
  2. 其他(项目和vendor)包
  3. Protocol Buffer导入
  4. 副作用导入
go
// Good
package main

import (
    "fmt"
    "hash/adler32"
    "os"

    "github.com/dsnet/compress/flate"
    "golang.org/x/text/encoding"

    foopb "myproj/foo/proto/proto"

    _ "myproj/rpc/protocols/dial"
)
导入重命名:
go
// Good - 清晰且具有描述性
import (
    foogrpc "path/to/package/foo_service_go_grpc"
    foopb "path/to/package/foo_service_go_proto"
)

// Avoid - 除非必要
import (
    foo "some/really/long/package/path"
)
绝不使用导入点(测试中除外):
go
// Bad
import . "foo"

// Good
import "foo"

Error Handling

错误处理

Return errors, don't panic:
go
// Good
func Open(path string) (*File, error) {
    f, err := os.Open(path)
    if err != nil {
        return nil, fmt.Errorf("open %s: %w", path, err)
    }
    return f, nil
}

// Bad - don't panic on errors
func Open(path string) *File {
    f, err := os.Open(path)
    if err != nil {
        panic(err)
    }
    return f
}
Error strings:
go
// Good - lowercase, no punctuation
err := fmt.Errorf("something bad happened")

// Bad
err := fmt.Errorf("Something bad happened.")
Handle errors:
go
// Good
if err := doSomething(); err != nil {
    return fmt.Errorf("failed to do something: %w", err)
}

// Bad - ignoring errors
_ = doSomething()
Indent error flow:
go
// Good
if err != nil {
    // error handling
    return err
}
// normal code

// Bad - avoid else after error
if err != nil {
    // error handling
} else {
    // normal code
}
Error wrapping:
go
// Good - use %w to wrap errors for errors.Is/As
return fmt.Errorf("process failed: %w", err)

// Good - use %v when you don't want wrapping
return fmt.Errorf("process failed: %v", err)
返回错误,不要panic:
go
// Good
func Open(path string) (*File, error) {
    f, err := os.Open(path)
    if err != nil {
        return nil, fmt.Errorf("open %s: %w", path, err)
    }
    return f, nil
}

// Bad - 不要在错误时panic
func Open(path string) *File {
    f, err := os.Open(path)
    if err != nil {
        panic(err)
    }
    return f
}
错误字符串:
go
// Good - 小写,无标点
err := fmt.Errorf("something bad happened")

// Bad
err := fmt.Errorf("Something bad happened.")
处理错误:
go
// Good
if err := doSomething(); err != nil {
    return fmt.Errorf("failed to do something: %w", err)
}

// Bad - 忽略错误
_ = doSomething()
错误流程缩进:
go
// Good
if err != nil {
    // 错误处理
    return err
}
// 正常代码

// Bad - 避免在错误处理后使用else
if err != nil {
    // 错误处理
} else {
    // 正常代码
}
错误包装:
go
// Good - 使用%w包装错误以支持errors.Is/As
return fmt.Errorf("process failed: %w", err)

// Good - 不希望包装时使用%v
return fmt.Errorf("process failed: %v", err)

Function Design

函数设计

Keep signatures simple:
go
// Good - signature on one line
func (r *Reader) Read(p []byte) (n int, err error)

// Good - named results when helpful
func WithTimeout(parent Context, d time.Duration) (ctx Context, cancel func())

// Bad - naked returns in long functions
func Process() (result int, err error) {
    // ... many lines ...
    result = 42
    return // unclear what's being returned
}
Avoid repetition:
go
// Good
func (c *Config) WriteTo(w io.Writer) (int64, error)

// Bad - repetitive
func (c *Config) WriteConfigTo(w io.Writer) (int64, error)
保持签名简洁:
go
// Good - 签名在一行
func (r *Reader) Read(p []byte) (n int, err error)

// Good - 必要时使用命名返回值
func WithTimeout(parent Context, d time.Duration) (ctx Context, cancel func())

// Bad - 长函数中使用裸返回
func Process() (result int, err error) {
    // ... 多行代码 ...
    result = 42
    return // 不清楚返回的内容
}
避免重复:
go
// Good
func (c *Config) WriteTo(w io.Writer) (int64, error)

// Bad - 重复冗余
func (c *Config) WriteConfigTo(w io.Writer) (int64, error)

Nil Slices

Nil切片

Prefer nil slices over empty slices:
go
// Good
var s []int // nil slice, len=0, cap=0

// Acceptable in most cases
s := []int{} // non-nil empty slice

// Don't force distinction between nil and empty
if len(s) == 0 { // works for both nil and empty
    // ...
}

// Bad
if s == nil { // usually not what you want
    // ...
}
优先使用nil切片而非空切片:
go
// Good
var s []int // nil切片,len=0,cap=0

// 大多数情况下可接受
s := []int{} // 非nil空切片

// 不要强行区分nil和空
if len(s) == 0 { // 对nil和空切片都有效
    // ...
}

// Bad
if s == nil { // 通常不是你想要的
    // ...
}

Interfaces

接口

Small interfaces:
go
// Good - single method interface
type Reader interface {
    Read(p []byte) (n int, err error)
}

// Good - composed interfaces
type ReadWriter interface {
    Reader
    Writer
}
Accept interfaces, return structs:
go
// Good
func Process(r io.Reader) (*Result, error)

// Avoid unless necessary
func Process(r *os.File) (*Result, error)
小接口:
go
// Good - 单方法接口
type Reader interface {
    Read(p []byte) (n int, err error)
}

// Good - 组合接口
type ReadWriter interface {
    Reader
    Writer
}
接收接口,返回结构体:
go
// Good
func Process(r io.Reader) (*Result, error)

// 除非必要,否则避免
func Process(r *os.File) (*Result, error)

Concurrency

并发

Document concurrency:
go
// Good - document when NOT safe
// Cache stores expensive computation results.
//
// Methods are not safe for concurrent use.
type Cache struct { ... }

// Good - document when safe
// Client is safe for concurrent use by multiple goroutines.
type Client struct { ... }
Context usage:
go
// Good - context as first parameter
func Process(ctx context.Context, data []byte) error

// Document if context behavior is special
// Run executes the worker's run loop.
//
// If the context is cancelled, Run returns a nil error.
func (w *Worker) Run(ctx context.Context) error
文档说明并发安全性:
go
// Good - 说明非并发安全
// Cache stores expensive computation results.
//
// Methods are not safe for concurrent use.
type Cache struct { ... }

// Good - 说明并发安全
// Client is safe for concurrent use by multiple goroutines.
type Client struct { ... }
Context使用:
go
// Good - 将context作为第一个参数
func Process(ctx context.Context, data []byte) error

// 若context行为特殊则需文档说明
// Run executes the worker's run loop.
//
// If the context is cancelled, Run returns a nil error.
func (w *Worker) Run(ctx context.Context) error

Testing

测试

Table-driven tests:
go
// Good
func TestParse(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        want    int
        wantErr bool
    }{
        {name: "valid", input: "123", want: 123},
        {name: "invalid", input: "abc", wantErr: true},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := Parse(tt.input)
            if (err != nil) != tt.wantErr {
                t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if got != tt.want {
                t.Errorf("Parse() = %v, want %v", got, tt.want)
            }
        })
    }
}
Test names:
go
// Good
func TestParse(t *testing.T)
func TestParse_InvalidInput(t *testing.T)
func TestClient_Get_Success(t *testing.T)

// Bad
func TestParseFunction(t *testing.T)
func Test_Parse(t *testing.T)
表驱动测试:
go
// Good
func TestParse(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        want    int
        wantErr bool
    }{
        {name: "valid", input: "123", want: 123},
        {name: "invalid", input: "abc", wantErr: true},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := Parse(tt.input)
            if (err != nil) != tt.wantErr {
                t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if got != tt.want {
                t.Errorf("Parse() = %v, want %v", got, tt.want)
            }
        })
    }
}
测试名称:
go
// Good
func TestParse(t *testing.T)
func TestParse_InvalidInput(t *testing.T)
func TestClient_Get_Success(t *testing.T)

// Bad
func TestParseFunction(t *testing.T)
func Test_Parse(t *testing.T)

Literal Formatting

字面量格式化

Field names in structs:
go
// Good - specify field names for external types
r := csv.Reader{
    Comma: ',',
    Comment: '#',
    FieldsPerRecord: 4,
}

// Good - field names optional for package-local types
okay := LocalType{42, "hello"}
Matching braces:
go
// Good
items := []*Item{
    {Name: "foo"},
    {Name: "bar"},
}

// Bad - misaligned braces
items := []*Item{
    {Name: "foo"},
    {Name: "bar"}}
结构体字段名:
go
// Good - 为外部类型指定字段名
r := csv.Reader{
    Comma: ',',
    Comment: '#',
    FieldsPerRecord: 4,
}

// Good - 包内类型可省略字段名
okay := LocalType{42, "hello"}
大括号匹配:
go
// Good
items := []*Item{
    {Name: "foo"},
    {Name: "bar"},
}

// Bad - 大括号对齐错误
items := []*Item{
    {Name: "foo"},
    {Name: "bar"}}

Package Design

包设计

Package size:
  • Not too large (thousands of lines in one package)
  • Not too small (one type per package)
  • Group related functionality
  • Standard library is a good example
Avoid utility packages:
go
// Bad - vague package names
package util
package common
package helper

// Good - specific, focused packages
package cache
package auth
package stringutil
包大小:
  • 不要过大(单个包数千行代码)
  • 不要过小(每个包仅一个类型)
  • 按相关功能分组
  • 标准库是很好的示例
避免工具类包:
go
// Bad - 模糊的包名
package util
package common
package helper

// Good - 具体、聚焦的包名
package cache
package auth
package stringutil

Common Patterns

常见模式

Options Pattern

选项模式

go
// Good - for optional configuration
type Options struct {
    Timeout time.Duration
    Retries int
}

func NewServer(addr string, opts Options) *Server

// Or using functional options
type Option func(*Server)

func WithTimeout(d time.Duration) Option {
    return func(s *Server) {
        s.timeout = d
    }
}

func NewServer(addr string, opts ...Option) *Server
go
// Good - 用于可选配置
type Options struct {
    Timeout time.Duration
    Retries int
}

func NewServer(addr string, opts Options) *Server

// 或使用函数式选项
type Option func(*Server)

func WithTimeout(d time.Duration) Option {
    return func(s *Server) {
        s.timeout = d
    }
}

func NewServer(addr string, opts ...Option) *Server

Constructor Pattern

构造函数模式

go
// Good - New for single type in package
package widget
func New() *Widget

// Good - NewX for multiple types
package widget
func NewWidget() *Widget
func NewGizmo() *Gizmo
go
// Good - 包内单个类型使用New
package widget
func New() *Widget

// Good - 多个类型使用NewX
package widget
func NewWidget() *Widget
func NewGizmo() *Gizmo

Cleanup Pattern

清理模式

go
// Good - document cleanup requirements
// Open opens a file for reading.
// The caller must call Close when done.
func Open(name string) (*File, error)

// Good - defer for cleanup
f, err := os.Open(filename)
if err != nil {
    return err
}
defer f.Close()
go
// Good - 文档说明清理要求
// Open opens a file for reading.
// The caller must call Close when done.
func Open(name string) (*File, error)

// Good - 使用defer进行清理
f, err := os.Open(filename)
if err != nil {
    return err
}
defer f.Close()

Least Mechanism

最少机制原则

Prefer simpler constructs:
  1. Use core language features first (channels, slices, maps, loops)
  2. Then standard library (http.Client, template engine)
  3. Finally, external dependencies (only if necessary)
go
// Good - use built-in
users := make(map[string]*User)

// Avoid - unless set operations are complex
import "github.com/deckarep/golang-set"
users := mapset.NewSet()
优先使用简单结构:
  1. 首先使用核心语言特性(通道、切片、映射、循环)
  2. 其次使用标准库(http.Client、模板引擎)
  3. 最后使用外部依赖(仅在必要时)
go
// Good - 使用内置特性
users := make(map[string]*User)

// Avoid - 除非集合操作复杂
import "github.com/deckarep/golang-set"
users := mapset.NewSet()

How I work

工作方式

When you ask me to help with Go code, I will:
  1. Analyze the code for style violations and clarity issues
  2. Suggest specific improvements citing relevant style principles
  3. Rewrite code sections to match professional Go style
  4. Add proper documentation following godoc conventions
  5. Format imports, grouping, and structure correctly
  6. Simplify complex code while maintaining correctness
  7. Apply idiomatic Go patterns and best practices
I prioritize clarity, simplicity, and maintainability. The goal is code that is easy to read, understand, and maintain.
当你请求我帮助处理Go代码时,我会:
  1. 分析代码中的风格违规和清晰度问题
  2. 建议具体的改进方案,并引用相关的风格原则
  3. 重写代码片段以匹配专业Go风格
  4. 添加符合godoc规范的正确文档
  5. 格式化导入、分组和结构
  6. 简化复杂代码,同时保持正确性
  7. 应用地道的Go模式和最佳实践
我优先考虑清晰性、简洁性和可维护性。目标是编写易于阅读、理解和维护的代码。

References

参考资料