Golang中的回调函数详解

Golang中的回调函数详解 我正在尝试理解回调函数。之前在JS中,我曾将它们用于事件监听器,但不知为何在Go中(可能是因为需要明确指定type,我不太确定),我很难理解其原理。我可以创建简单的回调,例如:

package main

import (
    "fmt"
)

func main() {
    run(example)
}

func example() {
    fmt.Println(2 + 2)
}



func run(f func()) {
    f()
}

但是当我尝试用另一种方式实现时,一切都乱套了。

package main

import "fmt"

func main() {
	total := run(example, 2, 2)
	fmt.Println(total)

}

func example(a int, b int) int {
	return a + b
}

func run(f func(a int, b int), a int, b int) int {
	f()
	return f()
}

除了Go文档中的Pig示例,有人能从其他角度帮我理解这个问题吗?


更多关于Golang中的回调函数详解的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复
  1. 你需要将 ab 传递给 f()f(a, b)
  2. example() 的类型是 func(int, int)int 而不是 func(int,int),当你声明一个参数的类型时,返回值也必须匹配。
  3. 你试图返回一个不期望返回任何内容的函数的结果,而 Go 期望你返回一个 int

更多关于Golang中的回调函数详解的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中,回调函数的核心是将函数作为参数传递。你的第二个示例存在几个关键问题:

主要问题分析

  1. 函数签名不匹配run函数期望接收func(a int, b int),但实际需要的是func(a int, b int) int
  2. 参数传递错误:没有将参数传递给回调函数
  3. 调用次数错误:调用了两次f()

修正后的代码

package main

import "fmt"

func main() {
    // 传递函数和参数
    total := run(example, 2, 2)
    fmt.Println(total) // 输出: 4
    
    // 使用匿名函数作为回调
    total2 := run(func(x, y int) int {
        return x * y
    }, 3, 4)
    fmt.Println(total2) // 输出: 12
}

// 回调函数:接收两个int参数,返回int
func example(a int, b int) int {
    return a + b
}

// run函数:接收函数参数和对应的参数
func run(f func(int, int) int, a int, b int) int {
    // 将参数传递给回调函数
    return f(a, b)
}

类型定义提升可读性

package main

import "fmt"

// 定义函数类型
type Operation func(int, int) int

func main() {
    // 使用类型定义
    result := calculate(example, 5, 3)
    fmt.Println(result) // 输出: 8
    
    // 减法回调
    result2 := calculate(subtract, 10, 4)
    fmt.Println(result2) // 输出: 6
}

func example(a, b int) int {
    return a + b
}

func subtract(a, b int) int {
    return a - b
}

func calculate(op Operation, x, y int) int {
    return op(x, y)
}

实际应用示例:事件处理

package main

import "fmt"

// 事件处理器类型
type EventHandler func(string)

// 事件发射器
type EventEmitter struct {
    handlers []EventHandler
}

// 注册事件处理器
func (e *EventEmitter) On(event string, handler EventHandler) {
    e.handlers = append(e.handlers, handler)
}

// 触发事件
func (e *EventEmitter) Emit(event string, data string) {
    for _, handler := range e.handlers {
        handler(data)
    }
}

func main() {
    emitter := &EventEmitter{}
    
    // 注册回调函数
    emitter.On("message", func(data string) {
        fmt.Printf("收到消息: %s\n", data)
    })
    
    emitter.On("message", func(data string) {
        fmt.Printf("消息长度: %d\n", len(data))
    })
    
    // 触发事件
    emitter.Emit("message", "Hello, Go!")
}

带错误处理的回调模式

package main

import (
    "fmt"
    "errors"
)

type Callback func(int, int) (int, error)

func main() {
    result, err := execute(safeDivide, 10, 2)
    if err != nil {
        fmt.Println("错误:", err)
    } else {
        fmt.Println("结果:", result)
    }
    
    // 触发错误的情况
    result2, err2 := execute(safeDivide, 10, 0)
    if err2 != nil {
        fmt.Println("错误:", err2)
    }
}

func safeDivide(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("除数不能为零")
    }
    return a / b, nil
}

func execute(cb Callback, x, y int) (int, error) {
    return cb(x, y)
}

关键点:

  1. Go中的回调需要明确定义函数签名
  2. 使用type定义函数类型可以提高代码可读性
  3. 回调函数调用时需要正确传递参数
  4. 函数签名(参数类型和返回值类型)必须完全匹配
回到顶部