go-functions
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGo Function Design
Go函数设计
Function Grouping and Ordering
函数分组与排序
Organize functions in a file by these rules:
- Functions sorted in rough call order
- Functions grouped by receiver
- Exported functions appear first, after /
struct/constdefinitionsvar - /
NewXxxconstructors appear right after the type definitionnewXxx - Plain utility functions appear toward the end of the file
Bad:
go
func (s *something) Cost() int {
return calcCost(s.weights)
}
type something struct{ ... }
func calcCost(n []int) int { ... }
func (s *something) Stop() { ... }
func newSomething() *something {
return &something{}
}Good:
go
type something struct{ ... }
func newSomething() *something {
return &something{}
}
func (s *something) Cost() int {
return calcCost(s.weights)
}
func (s *something) Stop() { ... }
func calcCost(n []int) int { ... }按以下规则在文件中组织函数:
- 函数按大致调用顺序排序
- 函数按接收者分组
- 导出函数出现在/
struct/const定义之后var - /
NewXxx构造函数紧跟在类型定义之后newXxx - 普通工具函数放在文件末尾
Bad:
go
func (s *something) Cost() int {
return calcCost(s.weights)
}
type something struct{ ... }
func calcCost(n []int) int { ... }
func (s *something) Stop() { ... }
func newSomething() *something {
return &something{}
}Good:
go
type something struct{ ... }
func newSomething() *something {
return &something{}
}
func (s *something) Cost() int {
return calcCost(s.weights)
}
func (s *something) Stop() { ... }
func calcCost(n []int) int { ... }Function Signature Formatting
函数签名格式化
Keep the signature on a single line when possible. When it must wrap, put all
arguments on their own lines with a trailing comma:
Bad:
go
func (r *SomeType) SomeLongFunctionName(foo1, foo2, foo3 string,
foo4, foo5, foo6 int) {
foo7 := bar(foo1)
}Good:
go
func (r *SomeType) SomeLongFunctionName(
foo1, foo2, foo3 string,
foo4, foo5, foo6 int,
) {
foo7 := bar(foo1)
}Shorten call sites by factoring out local variables instead of splitting
arbitrarily:
go
// Good: factor out locals
local := helper(some, parameters, here)
result := foo.Call(list, of, parameters, local)尽可能将签名放在一行。当必须换行时,将所有参数单独放在一行并添加 trailing comma:
Bad:
go
func (r *SomeType) SomeLongFunctionName(foo1, foo2, foo3 string,
foo4, foo5, foo6 int) {
foo7 := bar(foo1)
}Good:
go
func (r *SomeType) SomeLongFunctionName(
foo1, foo2, foo3 string,
foo4, foo5, foo6 int,
) {
foo7 := bar(foo1)
}通过提取局部变量而非随意拆分来简化调用代码:
go
// Good: factor out locals
local := helper(some, parameters, here)
result := foo.Call(list, of, parameters, local)Avoid Naked Parameters
避免裸参数
Naked parameters in function calls hurt readability. Add C-style comments for
ambiguous arguments:
go
// Bad
printInfo("foo", true, true)
// Good
printInfo("foo", true /* isLocal */, true /* done */)Better yet, replace naked parameters with custom types:
boolgo
type Region int
const (
UnknownRegion Region = iota
Local
)
func printInfo(name string, region Region, status Status)函数调用中的裸参数会损害可读性。为模糊的参数添加C风格注释:
go
// Bad
printInfo("foo", true, true)
// Good
printInfo("foo", true /* isLocal */, true /* done */)更好的方式是,用自定义类型替换裸参数:
boolgo
type Region int
const (
UnknownRegion Region = iota
Local
)
func printInfo(name string, region Region, status Status)Pointers to Interfaces
指向接口的指针
You almost never need a pointer to an interface. Pass interfaces as values — the
underlying data can still be a pointer.
go
// Bad: pointer to interface is almost always wrong
func process(r *io.Reader) { ... }
// Good: pass the interface value directly
func process(r io.Reader) { ... }If you need interface methods to modify the underlying data, the concrete type
stored in the interface must be a pointer — not the interface itself.
几乎永远不需要指向接口的指针。直接传递接口值——底层数据仍然可以是指针。
go
// Bad: pointer to interface is almost always wrong
func process(r *io.Reader) { ... }
// Good: pass the interface value directly
func process(r io.Reader) { ... }如果需要接口方法修改底层数据,接口中存储的具体类型必须是指针——而非接口本身。
Use %q
for Strings
%q对字符串使用%q
%qThe verb prints strings inside double quotes, making empty strings and
control characters visible:
%qgo
// Good: %q makes boundaries and special chars visible
fmt.Printf("value %q looks like English text", someText)
// Bad: manually adding quotes
fmt.Printf("value \"%s\" looks like English text", someText)Prefer in output intended for humans where the value could be empty or
contain control characters.
%q%qgo
// Good: %q makes boundaries and special chars visible
fmt.Printf("value %q looks like English text", someText)
// Bad: manually adding quotes
fmt.Printf("value \"%s\" looks like English text", someText)当输出面向人类且值可能为空或包含控制字符时,优先使用。
%qFormat Strings Outside Printf
在Printf外部定义格式化字符串
When declaring format strings outside a -style call, use . This
enables to perform static analysis:
Printfconstgo vetgo
// Bad: variable format string — go vet can't check it
msg := "unexpected values %v, %v\n"
fmt.Printf(msg, 1, 2)
// Good: const format string — go vet can validate
const msg = "unexpected values %v, %v\n"
fmt.Printf(msg, 1, 2)在类调用外部声明格式化字符串时,使用。这样可以执行静态分析:
Printfconstgo vetgo
// Bad: variable format string — go vet can't check it
msg := "unexpected values %v, %v\n"
fmt.Printf(msg, 1, 2)
// Good: const format string — go vet can validate
const msg = "unexpected values %v, %v\n"
fmt.Printf(msg, 1, 2)Naming Printf-style Functions
Printf风格函数的命名
Functions that accept a format string should end in . This lets
check format strings automatically:
fgo vetgo
// Good: go vet checks Wrapf format strings by default
func Wrapf(err error, format string, args ...any) error
// Bad: go vet won't check Wrap's format string
func Wrap(err error, format string, args ...any) errorIf using a non-standard name:
bash
go vet -printfuncs=wrapf,statusfRead when designing a
constructor with 3+ optional parameters.
go-functions/references/FUNCTIONAL-OPTIONS.md接受格式化字符串的函数名称应以结尾。这样可以自动检查格式化字符串:
fgo vetgo
// Good: go vet checks Wrapf format strings by default
func Wrapf(err error, format string, args ...any) error
// Bad: go vet won't check Wrap's format string
func Wrap(err error, format string, args ...any) error如果使用非标准名称:
bash
go vet -printfuncs=wrapf,statusf当设计带有3个及以上可选参数的构造函数时,请阅读。
go-functions/references/FUNCTIONAL-OPTIONS.mdQuick Reference
快速参考
| Topic | Rule |
|---|---|
| File ordering | Type -> constructor -> exported -> unexported -> utils |
| Signature wrapping | All args on own lines with trailing comma |
| Naked parameters | Add |
| Pointers to interfaces | Almost never needed; pass interfaces by value |
| Use for human-readable string output |
| Format string storage | Declare as |
| Printf function names | End with |
| 主题 | 规则 |
|---|---|
| 文件排序 | 类型 -> 构造函数 -> 导出函数 -> 未导出函数 -> 工具函数 |
| 签名换行 | 所有参数单独占一行并添加 trailing comma |
| 裸参数 | 添加 |
| 指向接口的指针 | 几乎不需要;按值传递接口 |
| 用于人类可读的字符串输出 |
| 格式化字符串存储 | 在Printf调用外部声明为 |
| Printf函数命名 | 以 |
See Also
另请参阅
- go-error-handling: Error return patterns and wrapping
- go-style-core: Line length and formatting principles
- go-declarations: Variable declaration and initialization patterns
- go-naming: Function and method naming conventions
- go-interfaces: Interface design and type assertions
- go-error-handling:错误返回模式与包装
- go-style-core:行长度与格式化原则
- go-declarations:变量声明与初始化模式
- go-naming:函数与方法命名约定
- go-interfaces:接口设计与类型断言