Golang中将函数赋值给变量的语法问题

Golang中将函数赋值给变量的语法问题 对于下面的代码,mi.Installer = ... 将被赋予函数,而 mi.Updater = ... 将引发编译器错误。这是合理的,没有问题。

我通过“实验”偶然发现了 mi.Installer = func() {a()} 的语法,它在后续使用时按预期工作,这很好。

然而,我还没有找到一篇权威文章说明这就是正确的方法,所以请原谅这个非常新手的问题……我通过尝试发现的这种语法是编写此代码的好/正确方式吗?或者是否有更好的语法?

我之所以这样问,是因为尽管它运行得很好,但在我看来它似乎很复杂。因为它看起来像是将一个包含 a() 的匿名函数赋值给它,这就像是在函数外面又包装了一层函数,似乎是一个不必要的额外函数调用。

type ModuleInfo struct {
	Installer func()
	Updater   func()
}

func (mi ModuleInfo) ModuleBoot() ModuleInfo {
	mi.Installer = func() {a()}
	mi.Updater = a()
	return mi
}

func a() {
	fmt.Println(`Hello World`)
}

更多关于Golang中将函数赋值给变量的语法问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

这篇文章非常有趣。谢谢!Go语言总是不断给我带来惊喜。

更多关于Golang中将函数赋值给变量的语法问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


唉,真是恍然大悟!当然,直接写函数名不加括号,它就能直接赋值,省去了那些复杂的操作。谢谢。

是的,这确实有些复杂,但这个空的无用函数很可能是一个装饰器。它可以为与 Installer 相关的存根函数添加额外的行为。你也可以直接赋值 mi.Updater = a,这本质上只是对你的函数进行“重命名空间”。但是,你真的应该读一下 Rob Pike 的方法 https://bit.ly/3cYYpoD。它可能看起来“复杂”,但它为配置/选项开启了非常有趣的途径。

我之所以这样问,是因为虽然它运行得很好,但在我看来似乎有些复杂。这看起来像是将一个包含函数 a() 的匿名函数赋值给它,这就像是在一个函数外面又包装了一层函数,似乎多了一次不必要的函数调用。

你说得对。从技术上讲,你是在赋值一个调用 a 的包装函数,而不是 a 本身。要将 a 赋值给 mi.Installer,只需像给其他变量赋值一样操作即可:

mi.Installer = a

在Go语言中,将函数赋值给变量的语法是正确的。mi.Installer = func() { a() } 是将一个匿名函数赋值给 Installer 字段,这个匿名函数在调用时会执行 a()。而 mi.Updater = a() 会导致编译错误,因为 a() 返回的是 nila() 函数没有返回值),而不是 func() 类型。

正确的做法是直接将函数名赋值给字段(不需要括号),或者使用匿名函数包装。以下是示例代码:

package main

import "fmt"

type ModuleInfo struct {
    Installer func()
    Updater   func()
}

func (mi ModuleInfo) ModuleBoot() ModuleInfo {
    // 方法1:直接赋值函数名(函数作为值)
    mi.Installer = a  // 注意:这里没有括号,传递的是函数本身

    // 方法2:使用匿名函数包装(适用于需要传递参数或额外逻辑的情况)
    mi.Updater = func() {
        fmt.Println("Updater called")
        a()
    }
    return mi
}

func a() {
    fmt.Println("Hello World")
}

func main() {
    mi := ModuleInfo{}
    mi = mi.ModuleBoot()
    mi.Installer() // 输出: Hello World
    mi.Updater()   // 输出: Updater called \n Hello World
}

关键点:

  1. 函数作为一等公民,可以直接赋值给变量或字段(无需括号)。
  2. 使用匿名函数包装时,会创建一个新的函数闭包,但不会导致额外的性能开销(编译器会优化)。
  3. 如果函数签名匹配(无参数、无返回值),直接赋值更简洁。

你的语法是正确的,但直接赋值函数名(mi.Installer = a)更简洁且效率相同。匿名函数包装仅在需要额外逻辑(如调用多个函数、添加参数等)时有必要。

回到顶部