在 Go 中传递函数:15 分钟从新手到专家

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

能否将函数作为参数传递?可以,这就是为什么它能改变一切

\n\n

您是否想过,在 Go 中能否像普通变量一样将一个函数传递给另一个函数?如果您来自 Python 或 JavaScript 的世界,这对您来说是一种常见的模式。但在 Go 中,尽管它非常严谨,函数作为参数 不仅仅是“可以”,它是该语言最强大的工具之一。

\n\n

我还记得第一次接触这个概念时的情景:当时我正在编写一个日志处理工具,发现自己重复编写同一个循环,只是内部逻辑不同。当我意识到只需将所需的函数作为参数传递时,解决方案就出现了。代码变得更简洁、更短、更易理解。在本文中,我将向您展示如何掌握 在 Go 中将函数传递给函数——从简单的示例到您明天在工作中就能使用的实际模式。

\n\n

顺便说一句,我们在 PythonLib 上经常看到像“Can functions be passed as parameters?”这样的问题,在 Stack Overflow 上有数千次浏览。让我们以 Go 为例,一劳永逸地搞清楚这个主题。

\n\n

Go 中函数作为参数是什么?

\n\n

在 Go 中,函数是 一等公民。这意味着它们可以:

\n
    \n
  • 赋值给变量
  • \n
  • 传递给其他函数
  • \n
  • 从函数中返回
  • \n
  • 存储在结构体和切片中
  • \n
\n\n

当我们谈论 函数作为参数 时,我们指的是一个函数接受另一个函数作为参数,并在其内部调用它。听起来很复杂?实际上比看起来要简单。

\n\n

语法:如何声明一个接受另一个函数的函数

\n\n

在 Go 中,您需要显式指定参数函数的类型。看起来像这样:

\n\n
// 声明一个函数类型\ntype Transformer func(string) string\n\n// 接受另一个函数的函数\nfunc processText(text string, transform Transformer) string {\n    return transform(text)\n}
\n\n

或者,您可以直接在签名中声明类型:

\n\n
func processText(text string, transform func(string) string) string {\n    return transform(text)\n}
\n\n

两种方式都可行。如果您计划重用该类型,第一种更方便。第二种适用于快速解决方案。

\n\n

简单示例:传递问候函数

\n\n

让我们编写一些贴近实际的东西。假设您有一个格式化用户名的函数,并且您想插入不同的问候语:

\n\n
package main\n\nimport "fmt"\n\n// 问候函数的类型\ntype Greeter func(name string) string\n\n// 接受问候语的函数\nfunc greetUser(name string, greeter Greeter) {\n    message := greeter(name)\n    fmt.Println(message)\n}\n\nfunc main() {\n    // 普通问候\n    normalGreet := func(name string) string {\n        return "你好," + name + "!"\n    }\n\n    // 正式问候\n    formalGreet := func(name string) string {\n        return "尊敬的 " + name + ",下午好。"\n    }\n\n    greetUser("安娜", normalGreet)\n    greetUser("安娜", formalGreet)\n}
\n\n

输出:

\n
你好,安娜!\n尊敬的 安娜,下午好。
\n\n

看到了吗?我们只是将不同的函数传递给了同一个 greetUser。这就是 将函数作为参数传递 的实际应用。

\n\n

回调函数:当需要处理结果时

\n\n

使用 函数作为参数 最常见的场景之一就是回调。您执行某个操作,并在操作完成时调用传递进来的函数。

\n\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\n// 模拟长时间加载数据的函数\nfunc fetchData(callback func(string)) {\n    fmt.Println("正在加载数据...")\n    time.Sleep(2 * time.Second) // 模拟延迟\n    data := "来自数据库的重要数据"\n    callback(data)                

博客

书籍推荐