Return 像 Golang 中的 'ok' 一样映射正常函数

Return map like 'ok' in Golang on normal functions

在 Go 中,以下工作(注意地图的一个使用有一个 return,另一个有两个 returns)

package main

import "fmt"

var someMap = map[string]string { "some key": "hello" }

func main() {
    if value, ok := someMap["some key"]; ok {
        fmt.Println(value)
    }

    value := someMap["some key"]
    fmt.Println(value)
}

但是,我不知道如何用我自己的函数做同样的事情。是否可以使用可选的 return 来实现类似的行为,例如 map?

例如:

package main

import "fmt"

func Hello() (string, bool) {
    return "hello", true
}

func main() {
    if value, ok := Hello(); ok {
        fmt.Println(value)
    }

    value := Hello()
    fmt.Println(value)
}

无法编译(由于错误 multiple-value Hello() in single-value context)...有没有办法使此语法适用于函数 Hello()

map 不同,因为它是内置的 type 而不是函数。访问 map 元素的 2 种形式由 Go Language Specification: Index Expressions 指定并由编译器支持。

使用函数你不能这样做。如果一个函数有 2 个 return 值,您必须“预期”它们两个或根本 none。

但是,您可以将任何 return 值分配给 Blank identifier:

s, b := Hello()    // Storing both of the return values

s2, _ := Hello()   // Storing only the first

_, b3 := Hello()   // Storing only the second

您也可以选择不存储任何 return 值:

Hello()            // Just executing it, but storing none of the return values

注意:您也可以将两个 return 值分配给空白标识符,尽管它没有用(除了验证它恰好有 2 个 return 值):

_, _ = Hello()     // Storing none of the return values; note the = instead of :=

您也可以在 Go Playground 上尝试这些。

辅助函数

如果您多次使用它并且不想使用空白标识符,请创建一个丢弃第二个 return 值的辅助函数:

func Hello2() string {
    s, _ := Hello()
    return s
}

现在您可以:

value := Hello2()
fmt.Println(value)

Go 1.18 泛型更新: Go 1.18 添加了泛型支持,现在可以编写一个泛型 First() 函数来丢弃第二个(或任何其他)return 值:

func First[T any](first T, _ ...any) T {
    return first
}

这在 github.com/icza/gog, as gog.First() 中可用(披露:我是作者)。

使用它:

value := First(Hello())
fmt.Println(value)

另外@icza的解释:

  • 我不建议在那里使用辅助函数。特别是如果 Hello 函数是您自己的函数。
  • 不过,如果自己驾驭不了,那还是用帮手吧。
  • 如果是自己的函数,最好改一下自己函数的签名。可能是你在某个地方犯了设计错误。

你也可以这样做:

package main

import "fmt"

func Hello() (string, bool) {
    return "hello", true
}

func main() {
    // Just move it one line above: don't use a short-if
    value, ok := Hello()
    if ok {
        fmt.Println(value)
    }
}