Go中下划线(空白标识符)的含义

时间:2014-06-23 00:30:48

标签: go

当我阅读Go文档时,我发现了这个:

  

您可以要求编译器通过尝试赋值来检查类型T是否实现了接口I:

type T struct{}
var _ I = T{} // Verify that T implements I.

我不明白_用于什么,我在其他作业中看过它但却无法理解它的含义。深入挖掘我发现它被称为“空白标识符”,但我不明白它们的用例:

_ = x // evaluate x but ignore it

成语仍然让我觉得有些陌生,所以我试图理解为什么我会这样做。

5 个答案:

答案 0 :(得分:29)

_是一个特殊的标识符,您可以分配任何内容但从不读取。在第一个例子中,您给出了:

var _ I = T{}

无法访问此变量,因此它将从生成的程序中进行优化。但是,如果类型T无法分配给接口I,则可能导致编译错误。所以在这种情况下,它被用作关于类型的静态断言。

第二种情况更为常见。虽然抛弃函数调用的结果似乎很奇怪,但在具有多个返回的函数中它会更有意义。考虑一个函数foo,它返回两个值,但您只对第一个值感兴趣?您可以使用_忽略第二个:

a, _ = foo()

您可以通过创建另一个变量来保留不需要的返回值来获得相同的效果,但此功能意味着您不必担心为其选择唯一的名称。

答案 1 :(得分:11)

这在允许多个返回值的语言中很常见。在某些情况下,您实际上并不关心其中一个返回值。

例如,在Go中,通常会返回错误。如果由于某种原因您不关心该错误,您可以选择忽略它:

value, _ := methodThatReturnsValueAndError()

但是,如果您指定它并且不使用它,则会出现编译错误:

value, err := methodThatReturnsValueAndError()
// if you don't use "err" .. its an error

答案 2 :(得分:4)

  

“计算机科学中只有两件事:缓存失效和命名事物”。 Tim Bray引用了Phil Karlton的话

这不需要命名。

在Go中,如果您不想使用afoo作为示例变量名称,则可以使用_。那就是它!他们可以写var a I = T{},结果会一样(除了未使用的变量是Go中的错误)。

对于空白标识符的其他用途,请阅读Effective Go

答案 3 :(得分:4)

简单来说,_是一个被忽略的值。如果您尝试这样做,Go不会允许未使用的局部变量并抛出编译错误。所以你欺骗编译器说"请忽略这个值"通过放置_

例如:

// Here range of os.Args returns index, value
for index, arg := range os.Args[1:] {
    fmt.Println(arg)
}

这里Go抛出了编译错误,因为你没有在循环中使用 index (未使用的局部变量)。现在你应该为_做索引,让编译器忽略它。

for _, arg := range os.Args[1:] {
    fmt.Println(arg)
}

答案 4 :(得分:3)

Go编译器几乎禁止声明但未使用的变量。像这样,

for i, myvalue := range myvar {
    total += mvalue
}

给定代码在此上下文中会稍微显示错误 - > "声明但未使用"。
因此,我们使用以下代码解决它:

for _, myvalue := range x {
    total += myvalue
}


至于 import 部分,它只是通过副作用来导入包。
请参阅此link