go
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWhat 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:
- Clarity - The code's purpose and rationale is clear to the reader
- Simplicity - The code accomplishes its goal in the simplest way possible
- Concision - The code has a high signal-to-noise ratio
- Maintainability - The code can be easily maintained
- Consistency - The code is consistent with the broader codebase
Go风格遵循以下核心原则,按重要性排序:
- 清晰性 - 代码的用途和设计思路对读者而言清晰易懂
- 简洁性 - 代码以最简单的方式实现目标
- 简洁性 - 代码具有高信噪比
- 可维护性 - 代码易于维护
- 一致性 - 代码与更广泛的代码库保持一致
Key style rules I enforce
我强制执行的关键风格规则
Formatting
格式化
All Go source files must conform to output:
gofmtbash
gofmt -w .- No fixed line length (prefer refactoring over splitting)
- Use or
MixedCaps(never snake_case)mixedCaps - Let the code speak for itself when possible
所有Go源文件必须符合的输出格式:
gofmtbash
gofmt -w .- 没有固定行长度(优先重构而非拆分)
- 使用或
MixedCaps(绝不使用snake_case)mixedCaps - 尽可能让代码自我说明
Naming Conventions
命名规范
Packages:
go
// Good
package creditcard
package tabwriter
package oauth2
// Bad
package credit_card
package tabWriter
package oAuth2Functions 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,cdb - Longer names in larger scopes: ,
userCountdatabaseConnection - Avoid type in name: not
usersuserSlice
Constants:
go
// Good
const MaxPacketSize = 512
const ExecuteBit = 1 << iota
// Bad
const MAX_PACKET_SIZE = 512
const kMaxBufferSize = 1024Initialisms:
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 stringReceiver 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、cdb - 大作用域使用长名称:、
userCountdatabaseConnection - 避免在名称中包含类型:使用而非
usersuserSlice
常量:
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 mathFunction 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) stringComment 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):
- Standard library packages
- Other (project and vendored) packages
- Protocol Buffer imports
- 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"导入分组(用空行分隔):
- 标准库包
- 其他(项目和vendor)包
- Protocol Buffer导入
- 副作用导入
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) errorTesting
测试
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 stringutilCommon 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) *Servergo
// 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) *ServerConstructor 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() *Gizmogo
// Good - 包内单个类型使用New
package widget
func New() *Widget
// Good - 多个类型使用NewX
package widget
func NewWidget() *Widget
func NewGizmo() *GizmoCleanup 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:
- Use core language features first (channels, slices, maps, loops)
- Then standard library (http.Client, template engine)
- 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()优先使用简单结构:
- 首先使用核心语言特性(通道、切片、映射、循环)
- 其次使用标准库(http.Client、模板引擎)
- 最后使用外部依赖(仅在必要时)
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:
- Analyze the code for style violations and clarity issues
- Suggest specific improvements citing relevant style principles
- Rewrite code sections to match professional Go style
- Add proper documentation following godoc conventions
- Format imports, grouping, and structure correctly
- Simplify complex code while maintaining correctness
- 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代码时,我会:
- 分析代码中的风格违规和清晰度问题
- 建议具体的改进方案,并引用相关的风格原则
- 重写代码片段以匹配专业Go风格
- 添加符合godoc规范的正确文档
- 格式化导入、分组和结构
- 简化复杂代码,同时保持正确性
- 应用地道的Go模式和最佳实践
我优先考虑清晰性、简洁性和可维护性。目标是编写易于阅读、理解和维护的代码。
References
参考资料
- Style Guide: https://google.github.io/styleguide/go/guide
- Style Decisions: https://google.github.io/styleguide/go/decisions
- Best Practices: https://google.github.io/styleguide/go/best-practices
- Effective Go: https://go.dev/doc/effective_go
- Code Review Comments: https://github.com/golang/go/wiki/CodeReviewComments
- Go Proverbs: https://go-proverbs.github.io/
- 风格指南: https://google.github.io/styleguide/go/guide
- 风格决策: https://google.github.io/styleguide/go/decisions
- 最佳实践: https://google.github.io/styleguide/go/best-practices
- Effective Go: https://go.dev/doc/effective_go
- 代码评审注释: https://github.com/golang/go/wiki/CodeReviewComments
- Go谚语: https://go-proverbs.github.io/