Skip to content
On this page

函数与方法

声明与调用

go
func Add(a, b int) int {
    return a + b
}

多返回值惯用 (T, error),调用方可忽略部分返回值(编译器可能对未使用报错,取决于是否为 _)。

变参

末参数可为 ...T,函数内为 []T

go
func Sum(nums ...int) int {
    s := 0
    for _, n := range nums {
        s += n
    }
    return s
}

展开切片:Sum(slice...)

命名返回值

go
func Split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return // 裸 return,返回已命名的 x, y
}

滥用会降低可读性;短函数或消除重复 return 变量名时较合适。

闭包

函数值可捕获外层变量,注意捕获的是变量本身(在 1.22 前与循环变量结合时易错;1.22 后循环变量语义已变,仍建议显式传参以降低心智负担):

go
func makeAdder(base int) func(int) int {
    return func(delta int) int {
        base += delta
        return base
    }
}

方法

带接收者的函数:func (r Receiver) M()func (r *Receiver) M()

值接收者 vs 指针接收者

值接收者指针接收者
拷贝接收者,大结构体成本高不拷贝整个结构体
不能通过方法修改原字段(改的是副本)可修改原实例
nil 指针值接收者调用会 panic(对指针解引用)常见允许 nil 接收者,在方法内判空

一致性:同一类型方法集建议统一指针或值接收者,避免混用令调用者困惑。

方法集(Method sets)

接口 satisfied 时,T 的方法集含值接收者方法;*T 的方法集含值与指针接收者方法。将 T 赋给接口时,仅 T 的方法集可用;将 *T 赋给接口时两者皆可(规范中的 promotion 规则)。

递归

与多数语言相同;注意栈深度与尾递归未做特殊优化。

init

每个包可有多个 func init(),在 main 之前、导入依赖初始化之后按依赖顺序执行;勿写复杂逻辑或依赖顺序难控的副作用。

技术文库