函数是一种类型,可以赋值给变量或作为参数传递。例如:
// 定义一个函数类型
type Add func(a int, b int) int
// 定义一个符合该类型的函数
func add(a int, b int) int {
return a + b
}
// 将函数赋值给变量
var f Add = add
// 将函数作为参数传递
func apply(op Add, a int, b int) int {
return op(a, b)
}
fmt.Println(apply(f, 3, 4)) // 输出 7
Go 语言只有值传递一种方式,但是可以通过指针或接口来实现引用传递的效果。例如:
// 值传递,不会改变原始数据
func swap(a int, b int) {
a, b = b, a
}
x := 1
y := 2
swap(x, y)
fmt.Println(x, y) // 输出 1 2
// 指针传递,可以改变原始数据
func swapByPointer(a *int, b *int) {
*a, *b = *b, *a
}
x := 1
y := 2
swapByPointer(&x, &y)
fmt.Println(x,y) // 输出 2 1
// 接口传递,可以改变原始数据(如果接口的动态类型是指针)
type Swapper interface {
Swap()
}
type Point struct {
x int
y int
}
func (p *Point) Swap() {
p.x , p.y = p.y , p.x
}
func swapByInterface(s Swapper) {
s.Swap()
}
p := &Point{1 ,2}
swapByInterface(p)
fmt.Println(p.x , p.y ) // 输出 2 1
Go 语言中有命名返回值和匿名返回值两种方式。例如:
// 命名返回值,可以省略 return 后面的表达式,但是可能导致歧义或错误。
func divide(a int ,b int ) (q ,r int ) {
q = a / b
r = a % b
return // 等价于 return q ,r
}
q ,r := divide(7 ,3)
fmt.Println(q,r ) // 输出 2 1
func divideWithError(a int,b int)(q,r error){
if(b ==0){
r = errors.New("division by zero")
return // 等价于 return q,r ,但是此时 q 是未初始化的零值。
}
q = a /b
return // 等价于 return q,r ,但是此时 r 是未初始化的零值。
}
defer 关键字和 panic/recover 函数在返回值处理中有特殊的作用。例如:
// defer 关键字可以在函数返回前执行一些操作,比如关闭文件、释放锁等。
func readFile(filename string)(content string,err error){
file,err := os.Open(filename)
if err != nil{
return "",err
}
defer file.Close() // 延迟关闭文件
buf,err := ioutil.ReadAll(file)
if err != nil{
return "",err
}
content = string(buf)
return content,nil
}
// panic/recover 函数可以用于处理异常情况,比如数组越界、空指针等。
func safeDivide(a,b float64)(result float64,err error){
defer func(){
if e:= recover();e!=nil{
err = fmt.Errorf("%v",e)// 捕获异常并转换为 error 类型。
}
}()
if b == 0{
panic("division by zero") // 抛出异常
}
result = a / b
return result,nil
}
result,err := safeDivide(10,0)
if err != nil{
fmt.Println(err) // 输出 division by zero
}
延迟函数和闭包是 Go 语言中的高级特性,可以用于实现高阶函数或生成器等功能。例如:
// 延迟函数可以访问外部函数的局部变量,甚至修改它们。
func printNumbers() {
i := 0
defer fmt.Println(i) // 输出 0
i++
defer fmt.Println(i) // 输出 1
return
}
printNumbers()
// 闭包是指能够捕获外部变量的匿名函数,可以用于实现高阶函数或生成器等功能。
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x // 捕获外部变量 sum
return sum
}
}
f := adder()
fmt.Println(f(1)) // 输出 1
fmt.Println(f(2)) // 输出 3
fmt.Println(f(3)) // 输出 6