为什么Go语言允许编译未使用的函数参数?

huangapple go评论85阅读模式
英文:

Why does Go allow compilation of unused function parameters?

问题

从C语言转到Go语言时,一个比较显著的特点是,如果程序中声明了一个未使用的变量,编译器将不会构建你的程序。那么,为什么在这个程序中声明了一个未使用的参数,却能够构建成功呢?

func main() {
    print(computron(3, -3));
}

func computron(param_a int, param_b int) int {
    return 3 * param_a;
}

在Go语言中,编译器允许声明未使用的参数。这是因为在函数定义中,你可能会使用到参数,但在特定的函数调用中,可能并不需要使用到所有的参数。因此,Go语言的编译器允许这种情况的发生。

英文:

One of the more notable aspects of Go when coming from C is that the compiler will not build your program if there is an unused variable declared inside of it. So why, then, is this program building if there is an unused parameter declared in a function?

func main() {
	print(computron(3, -3));
}


func computron(param_a int, param_b int) int {
	return 3 * param_a;
}

答案1

得分: 30

没有官方的原因,但在golang-nuts上给出的原因是:

未使用的变量始终是编程错误,而编写一个不使用所有参数的函数是常见的。
可以将这些参数命名为未命名(使用_),但这可能会与以下函数混淆:
func foo(_ string, _ int) // 这个函数应该做什么?

即使它们未使用,名称也提供了重要的文档。
安德鲁

有时,拥有未使用的参数对于满足接口是很重要的,一个例子可能是在加权图上操作的函数。如果您想要实现一个具有所有边缘上统一成本的图,那么考虑节点是无用的:

func (graph *MyGraph) Distance(node1,node2 Node) int {
return 1
}

正如该线程所指出的,只允许未使用的参数命名为_(例如Distance(_,_ Node))是有道理的,但由于Go 1未来兼容性保证,现在为时已晚。正如还提到的,对此的一个可能的反对意见是,即使未使用,参数也可以隐式地提供文档。

简而言之:除了他们仅仅做出了一个最终是任意的(但仍然是有根据的)决定,即未使用的参数比未使用的局部变量和导入更重要和有用之外,没有具体的、具体的答案。如果曾经有一个强有力的设计原因,那么它没有在任何地方记录下来。

英文:

There's no official reason, but the reason given on golang-nuts is:

> Unused variables are always a programming error, whereas it is common
> to write a function that doesn't use all of its arguments.
>
> One could leave those arguments unnamed (using ), but then that might
> confuse with functions like
>
> func foo(
string, _ int) // what's this supposed to do?
>
> The names, even if they're unused, provide important documentation.
>
> Andrew

https://groups.google.com/forum/#!topic/golang-nuts/q09H61oxwWw

Sometimes having unused parameters is important for satisfying interfaces, one example might be a function that operates on a weighted graph. If you want to implement a graph with a uniform cost across all edges, it's useless to consider the nodes:

func (graph *MyGraph) Distance(node1,node2 Node) int {
    return 1
}

As that thread notes, there is a valid argument to only allow parameters named as _ if they're unused (e.g. Distance(_,_ Node)), but at this point it's too late due to the Go 1 future-compatibility guarantee. As also mentioned, a possible objection to that anyway is that parameters, even if unused, can implicitly provide documentation.

In short: there's no concrete, specific answer, other than that they simply made an ultimately arbitrary (but still educated) determination that unused parameters are more important and useful than unused local variables and imports. If there was once a strong design reason, it's not documented anywhere.

答案2

得分: 4

主要原因是能够实现规定具有特定参数的特定方法的接口,即使在实现中没有使用所有参数。这在@Jsor的回答中有详细说明。

另一个很好的原因是未使用的(局部)变量通常是错误或语言特性的结果(例如,在块中使用短变量声明:=,无意中遮蔽了“外部”变量),而未使用的函数参数几乎从不是错误的结果。

另一个原因是为了提供“向前”兼容性。如果发布一个库,不能更改或扩展参数列表,否则会破坏向后兼容性(在Go中没有函数重载:如果要使用具有不同参数的2个变体,它们的名称也必须不同)。

您可以提供一个导出的函数或方法,并在其中添加额外的(尚未使用的)或可选的参数(例如,hints),以便在将来的版本/发布中可能会使用它们。

这样做早期将使使用您的库的其他人不必更改其代码。

让我们看一个例子:

您想创建一个格式化函数:

// FormatSize将指定的大小(字节)格式化为字符串。
func FormatSize(size int) string {
    return fmt.Sprintf("%d bytes", size)
}

您也可以立即添加一个额外的参数:

// FormatSize将指定的大小(字节)格式化为字符串。
// flags可以用于更改输出格式。尚未使用。
func FormatSize(size int, flags int) string {
    return fmt.Sprintf("%d bytes", size)
}

然后,稍后您可以改进您的库和FormatSize()函数,以支持以下格式化标志:

const (
    FlagAutoUnit      = 1 << iota // 自动格式化为KB、MB、GB等。
    FlagSI                        // 使用SI转换(1000而不是1024)
    FlagGroupDecimals             // 使用十进制分组格式化数字
)

// FormatSize将指定的大小(字节)格式化为字符串。
// flags可以用于更改输出格式。
func FormatSize(size int, flags int) string {
    var s string

    // 检查标志并相应地进行格式化
    // ...

    return s
}
英文:

The main reason is to be able to implement interfaces that dictate specific methods with specific parameters, even if you don't use all of them in your implementation. This is detailed in @Jsor's answer.

Another good reason is that unused (local) variables are often the result of a bug or the use of a language feature (e.g. use of short variable declaration := in a block, unintentionally shadowing an "outer" variable) while unused function parameters never (or very rarely) are the result of a bug.

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).

You may provide an exported function or method and add extra - not yet used - or optional parameters (e.g. hints) to it in the spirit that you may use them in a future version / release of your library.

Doing so early will give you the benefit that others using your library won't have to change anything in their code.

Let's see an example:

You want to create a formatting function:

// FormatSize formats the specified size (bytes) to a string.
func FormatSize(size int) string {
    return fmt.Sprintf(&quot;%d bytes&quot;, size)
}

You may as well add an extra parameter right away:

// FormatSize formats the specified size (bytes) to a string.
// flags can be used to alter the output format. Not yet used.
func FormatSize(size int, flags int) string {
    return fmt.Sprintf(&quot;%d bytes&quot;, size)
}

Then later you may improve your library and your FormatSize() function to support the following formatting flags:

const (
    FlagAutoUnit      = 1 &lt;&lt; iota // Automatically format as KB, MB, GB etc.
    FlagSI                        // Use SI conversion (1000 instead of 1024)
    FlagGroupDecimals             // Format number using decimal grouping
)

// FormatSize formats the specified size (bytes) to a string.
// flags can be used to alter the output format.
func FormatSize(size int, flags int) string {
    var s string

    // Check flags and format accordingly
    // ...

    return s
}

huangapple
  • 本文由 发表于 2014年3月21日 10:48:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/22549228.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定