问题 Go中的未命名参数是什么?


我正在Go for Go中编写一个解析器,为了测试它我从github项目中下载了一堆文件。
https://github.com/andlabs/ui 我碰到了一个包含这段代码的文件:

func moveLabel(*Button) {
    from := movingCurrent
    to := 0
    if from == 0 {
        to = 1
    }
    movingBoxes[from].Delete(0)
    movingBoxes[to].Append(movingLabel, false)
    movingCurrent = to
}

它让我有点困惑,看到指向a的指针 Button 没有名称作为函数参数,这使得无法从函数内部引用。
但是,鉴于编译器没有抱怨,它似乎在语法上是正确的。
Go中的unamed函数参数的目的是什么?


3669
2017-12-03 18:06


起源

添加了更多详细信息,说明(基于规范)和答案的链接。 - icza


答案:


未命名的参数完全有效。该 参数声明 来自规范:

ParameterDecl  = [ IdentifierList ] [ "..." ] Type .

如你所见, IdentifierList (标识符名称或名称)在方括号中,表示它 可选的。只有 Type 是必须的。

这是因为名称对于调用方法或函数的人来说并不重要。重要的是参数的类型及其顺序。这个答案详细说明: 在Golang中获取方法参数名称

通常,您可以命名变量和参数,以便可以引用它们。

当你没有说出什么名字时,那是因为你不想引用它。

所以问题应该是: 为什么我不想参考参数?

例如因为参数 “在那儿” (它被传递),但你不需要它,你不想使用它。如果我不需要它,它为什么会在那里?

因为某人或某事 使然 具体参数在那里。例如,您希望实现一个接口,或者您希望传递一个函数值,其签名由期望的函数类型定义。

我们来看一个例子吧。我们有以下内容 MyWriter 接口:

type MyWriter interface {
    Write(p []byte) error
}

简化 io.Writer 它只返回错误,但不报告写入的字节数。如果你想提供一个只丢弃数据的实现(类似于 ioutil.Discard),然后实现不使用(不需要使用)其参数:

type DiscardWriter struct{}

func (DiscardWriter) Write([]byte) error { return nil }

这就是全部:我们不使用接收器,我们不使用参数。两者都可以是未命名的。并且实现正是它应该做的。

这样做(使用未命名的参数)也是如此 文件 该值未被使用/引用。

另一个原因可以是提供 前锋 兼容性。如果您发布了库,则无法在不破坏向后兼容性的情况下更改或扩展参数列表(在Go中没有函数重载:如果您想要2个具有不同参数的变体,它们的名称也必须不同)。因此,您可以尽早声明带有其他参数的导出函数或方法,但由于您尚未使用它们,因此可能会将它们保留为未命名。这个答案详细说明了这方面的一个例子: 为什么Go允许编译未使用的函数参数?

这里要注意的一件事是你不能混合命名和未命名的参数。如果你说出一些名字,你必须全名。如果你不需要所有,你可以使用 空白标识符 像在这个例子中:

一个简单的Web服务器响应 "Hello" 所有请求的文本:

http.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
    io.WriteString(w, "Hello")
})
panic(http.ListenAndServe(":8080", nil))

处理程序函数发回 "Hello" 文本仅使用响应编写器 w,但不是请求结构,因此空白标识符用作其名称。

另一个相关问题:

为什么在向Golang中的结构添加方法时必须声明变量名?

也有些相关,但关于使用/命名返回值:

在普通函数中返回Golang中的'ok'映射

关于获取方法/函数参数名称:

在Golang中获取方法参数名称


14
2017-12-03 18:19