Go 中有未命名的参数吗? [英] Is unnamed arguments a thing in Go?

查看:20
本文介绍了Go 中有未命名的参数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing a parser in Go for Go, and to test it I downloaded a bunch of files from github projects.
In https://github.com/andlabs/ui I bumped into a file containing this piece of code:

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

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

It confuse me a bit to see a pointer to a Button without a name as a function argument, which makes it impossible to reference from inside the function.
However, it seems to be syntactically correct given that the compiler doesn't complains.
What is the purpose of unamed functions arguments in Go?

推荐答案

未命名的参数完全有效.规范中的参数声明:

Unnamed parameters are perfectly valid. The Parameter declaration from the spec:

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

如您所见,IdentifierList(标识符名称或名称)位于方括号中,这意味着它是可选的.只需要Type.

As you can see, the IdentifierList (the identifier name or names) is in square brackets, which means it's optional. Only the Type is required.

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

The reason for this is because the names are not really important for someone calling a method or a function. What matters is the types of the parameters and their order. This is detailed in this answer: Getting method parameter names in Golang

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

Generally you name variables and parameters so that you can refer to them.

如果你不命名某事,那是因为你不想提及它.

When you don't name something, it's because you don't want to refer to it.

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

比如因为参数"is there"(它是通过的),但是你不需要它,你不想使用它.如果我不需要它,它为什么会在那里?

For example because the parameter "is there" (it is passed), but you don't need it, you don't want to use it. Why would it be there if I don't need it?

因为某人或某事规定特定参数存在.例如,您想要实现一个接口,或者您想要传递一个函数值,其签名由预期的函数类型定义.

Because someone or something dictates for specific parameters to be there. For example you want to implement an interface, or you want to pass a function value whose signature is defined by the function type that is expected.

让我们看一个例子.我们有如下 MyWriter 接口:

Let's see an example. We have the following MyWriter interface:

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

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

A simplified io.Writer which only returns an error, but does not report the number of bytes written. If you'd want to provide an implementation which just discards the data (similar to ioutil.Discard), then the implementation does not use (does not need to use) its argument:

type DiscardWriter struct{}

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

仅此而已:我们不使用接收者,我们不使用参数.两者都可以不命名.并且实现完全按照它应该做的.

And that's all: we don't use the receiver, we don't use the argument. Both can be unnamed. And the implementation does exactly what it should.

这样做(使用未命名的参数)还记录该值未被使用/引用.

Doing so (using unnamed parameters) also documents that the value is not used / referred to.

另一个原因可能是提供向前兼容性.如果你发布了一个库,你就不能在不破坏向后兼容性的情况下更改或扩展参数列表(在 Go 中没有函数重载:如果你想要 2 个具有不同参数的变体,它们的名称也必须不同).所以你可以提前声明一个带有附加参数的导出函数或方法,但由于你还没有使用它们,你可以不命名它们.此答案中详细说明了一个示例:为什么 Go 允许编译未使用的函数参数?

Another reason can be to provide forward compatibility. If you release a library, you can't change or extend the parameter list without breaking backward compatibility (and in Go there is no function overloading: if you want 2 variants with different parameters, their names must be different too). So you may declare an exported function or method with additional parameters early, but since you don't use them yet, you may leave them unnamed. An example of this is detailed in this answer: Why does Go allow compilation of unused function parameters?

这里要注意的一点是,您不能混合使用命名参数和未命名参数.如果你说出一些,你必须说出所有.如果您不需要全部,您可以使用 空白标识符,如下例所示:

One thing to note here is that you can't mix named and unnamed parameters. If you name some, you must name all. If you don't need all, you may use the blank identifier like in this example:

一个简单的网络服务器,它以 "Hello" 文本响应所有请求:

A simple web server which responds with the "Hello" text to all requests:

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

返回"Hello"文本的处理函数只使用响应编写器w,而不使用请求结构,因此使用空白标识符作为其名称.

The handler function sending back the "Hello" text only uses the response writer w, but not the request structure, so the blank identifier is used as its name.

另一个相关问题:

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

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

Also somewhat related, but regarding using / naming returned values:

返回地图,如确定"Golang 上的普通函数

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

And regarding getting method / function parameter names:

在Golang中获取方法参数名称

这篇关于Go 中有未命名的参数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆