为 struct 字段赋值时.
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("configure")
return fs
})(),
我认为这等同于只调用newFlagSet("configuration").这样写有什么好处呢?
在阅读资料时提出问题.需要知道他为什么写成这样.
为 struct 字段赋值时.
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("configure")
return fs
})(),
我认为这等同于只调用newFlagSet("configuration").这样写有什么好处呢?
在阅读资料时提出问题.需要知道他为什么写成这样.
在quick search之后,这个代码来自tailscale/tailscale
, cmd/tailscale/cli/configure.go#var configureCmd = &ffcli.Command{}
var configureCmd = &ffcli.Command{
Name: "configure",
ShortHelp: "[ALPHA] Configure the host to enable more Tailscale features",
LongHelp: strings.TrimSpace(`
The 'configure' set of commands are intended to provide a way to enable different
services on the host to use Tailscale in more ways.
`),
FlagSet: (func() *flag.FlagSet {
fs := newFlagSet("configure")
return fs
})(),
Subcommands: configureSubcommands(),
Exec: func(ctx context.Context, args []string) error {
return flag.ErrHelp
},
}
该代码使用function literal(匿名函数),然后立即调用该函数.
这就是众所周知的Immediately-Invoked Function Expression (IIFE)分.这在诸如JavaScript之类的语言中更为常见,但在Go中也很有用.
In Go, IIFE allows you to isolate a piece of logic that produces a value, creating a scoped environment for variables that will not pollute the surrounding namespace.
The variables used within the anonymous function (fs
in this case) do not escape into the surrounding code. This makes the code easier to reason about, as the variables live only as long as they are needed.
虽然FlagSet: newFlagSet("configure"),
确实相当于FlagSet: (func() *flag.FlagSet { fs := newFlagSet("configure"); return fs})()
,但第二种形式的一些优势可能是:
newFlagSet("configure")
的修改需要更复杂的操作或计算,这些更改可以很容易地合并到匿名函数中,而不会改变configureCmd
的 struct .然而,看看tailscale code个人,这一特定的生活使用似乎仅限于这一次.