Go语言中声明中的"_, "(下划线逗号)是什么?

128

我好像无法理解这种变量声明:

_, prs := m["example"]

"_," 到底是做什么的,为什么他们会像这样声明变量而不是...
prs := m["example"]

(我在 Go by Example: Maps 中发现了它。)

5
请先查看 spec,以获取未来语言问题的答案。这份规范应该可以回答你所有的问题。 - fuz
作为注释:prs 可能代表 "present"。你的示例代码正在检查 m 映射中是否存在或不存在 "example" 条目。 - dyoo
10
@FUZxxl 是的,我之前看过那里,但是由于我不知道这个功能的名称,所以我没有找到它。而且我发现编程语言的官方规范并不是很通俗易懂,更愿意通过实例来学习。 - Kansuler
可能是 在 Go 中下划线(空标识符)的含义 的重复。 - Dave C
11
@FUZxxl: 我不知道。在SO上提出的大多数问题可能都有答案可供查询。存在一个阈值,在该阈值以下,应该不会提出问题,但我认为这个问题并没有低于那个阈值。 - thb
显示剩余2条评论
9个回答

157
避免了为返回值声明所有变量的麻烦。
它被称为空白标识符

如下:

_, y, _ := coord(p)  // coord() returns three values; only interested in y coordinate

那样的话,您就不必声明一个您不会使用的变量:Go 不允许这样做。相反,使用“_”来忽略该变量。
其他'_'用例是用于导入
由于它丢弃了返回值,当您只想检查返回值中的一个时,它非常有用,例如在 "Effective Go, map" 中所示的 "How to test key existence in a map?"。
_, present := timeZone[tz]

为了在不考虑实际值的情况下测试映射中是否存在,您可以使用空白标识符,即简单的下划线(_)。
空白标识符可以赋值或声明为任何类型的任何值,并且可以安全地丢弃该值。
为了测试映射中是否存在,请在通常用于值的变量位置使用空白标识符。
正如Jsor评论中所说: “普遍接受的标准”是将成员资格测试变量称为“ok”(检查通道读取是否有效也是如此)
这使您可以将其与测试相结合。
if _, err := os.Stat(path); os.IsNotExist(err) {
    fmt.Printf("%s does not exist\n", path)
}

你还可以在循环中找到它:
如果你只需要范围中的第二个项(值),使用空白标识符下划线来丢弃第一个:
sum := 0
for _, value := range array {
    sum += value
}

谢谢您提供这个好的例子。我花了一些时间思考才理解这个概念,但现在我明白了! - Kansuler
请注意,IME“普遍接受的标准”是将成员资格测试变量称为“ok”(检查通道读取是否有效也是如此)。 - Linear
1
@Jsor 我同意。我已经在答案中包含了你的评论以增加可见性,并添加了一些额外的例子。 - VonC

79

Go编译器不允许您创建从未使用过的变量。

for i, value := range x {
   total += value
}

上述代码将返回一个错误信息 "i declared and not used"。

由于我们在循环内部没有使用 i,所以需要将其更改为以下内容:

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

16
理解为什么会有一个下划线作为空白标识符的原因,你第一句话非常重要。 - Tarik

5
空白标识符可用于语法要求变量名称但程序逻辑不需要时,例如当我们仅需要元素值时,可以丢弃不想要的循环索引。

4

_是空白标识符,意思是应该将其分配的值丢弃。

在这里,应该被分配的值是example键的值。第二行代码会丢弃存在布尔值,并将该值存储在prs中。
因此,只需检查地图中是否存在就可以丢弃值。这可以用于将地图用作集合。


4
未使用变量的一个很好的用例是在只需要部分输出时。在下面的示例中,我们只需要打印该值(州人口)。
package main
import (
    "fmt"
)
func main() {
          statePopulations := map[string]int{
          "California": 39250017,
          "Texas":      27862596,
          "Florida":    20612439,
          }
          for _, v := range statePopulations {
          fmt.Println(v)
    }
}

2

Golang中的_(下划线)被称为Blank Identifier。标识符是程序组件的用户定义名称,用于识别目的。 Golang有一个特殊功能,可以使用Blank Identifier定义和使用未使用的变量。 未使用的变量是指用户在整个程序中定义但从未使用过的变量。 当Go编译器遇到声明但未使用的变量时会抛出错误。现在我们可以简单地使用空白标识符而不声明任何变量。

   // Golang program to show the compiler
// throws an error if a variable is
// declared but not used

package main

import "fmt"

// Main function
func main() {

    // calling the function
    // function returns two values which are
    // assigned to mul and div identifier
    mul, div := mul_div(105, 7)

    // only using the mul variable
    // compiler will give an error
    fmt.Println("105 x 7 = ", mul)
}

// function returning two
// values of integer type
func mul_div(n1 int, n2 int) (int, int) {

    // returning the values
    return n1 * n2, n1 / n2
}

输出

./prog.go:15:7: div declared and not used

让我们使用空白标识符来修正上面的程序。只需使用 _ (下划线) 替换 div 标识符即可。它允许编译器忽略该特定变量的已声明但未使用的错误。

    // Golang program to the use of Blank identifier

package main

import "fmt"

// Main function
func main() {

    // calling the function
    // function returns two values which are
    // assigned to mul and blank identifier
    mul, _ := mul_div(105, 7)

    // only using the mul variable
    fmt.Println("105 x 7 = ", mul)
}

// function returning two
// values of integer type
func mul_div(n1 int, n2 int) (int, int) {

    // returning the values
    return n1 * n2, n1 / n2
}

输出

105 x 7 =  735

2
基本上, _ 被称为空白标识符。在GO中,我们不能有未使用的变量。
例如,在迭代数组时,如果您使用 value := range ,则不需要一个用于迭代的 i 值。但是,如果省略 i 值,则会返回错误。但是,如果声明了 i 并且没有使用它,也会返回错误。
因此,这就是我们必须使用 _ 的地方。
还可以在将来不想要函数的返回值时使用它。
"最初的回答"

2

它被称为空白标识符,并且在您希望丢弃将要返回的值并不引用它的情况下有所帮助。

我们使用它的一些场景:

  • 函数返回一个值,而您不打算在未来使用它
  • 您想要迭代并需要一个您将不使用的 i 值

1

在Golang中不允许使用未使用的变量

如果你来自其他编程语言,可能会感到有些困难。但这会导致更加清晰的代码。因此,通过使用 _,我们表明知道那里有一个变量,但我们不想使用它,并告诉编译器不要对此发出投诉。 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接