Return map like 'ok' in Golang on normal functions

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

Return map like 'ok' in Golang on normal functions

问题

在Go语言中,以下代码是有效的(注意map的用法,一个返回一个值,另一个返回两个值):

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

然而,我不知道如何在自己的函数中实现类似的行为。是否可以像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()的语法能够工作?

英文:

In Go, the following works (note one use of the map has one return, the other has two 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)
}

However, I have no idea how to do this same thing with my own function. Is it possible to have similar behavior with an optional return like map?

For example:

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

Wont compile (due to the error multiple-value Hello() in single-value context) ... is there a way to make this syntax work for the function Hello()?

答案1

得分: 47

map不同于函数,因为它是一种内置的类型而不是函数。访问map元素的两种形式由Go语言规范:索引表达式指定,并由编译器支持。

对于函数,你不能这样做。如果一个函数有两个返回值,你必须“期望”它们都存在或者都不存在。

然而,你可以将任何一个返回值赋给空白标识符

s, b := Hello()    // 存储两个返回值

s2, _ := Hello()   // 只存储第一个返回值

_, b3 := Hello()   // 只存储第二个返回值

你也可以选择不存储任何返回值:

Hello()            // 只执行它,不存储任何返回值

注意:你也可以将两个返回值都赋给空白标识符,尽管它没有用处(除了验证它确实有两个返回值):

_, _ = Hello()     // 不存储任何返回值;注意使用 = 而不是 :=

你也可以在Go Playground上尝试这些代码。

辅助函数

如果你多次使用它,并且不想使用空白标识符,可以创建一个辅助函数来丢弃第二个返回值:

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

现在你可以这样做:

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

Go 1.18泛型更新: Go 1.18添加了泛型支持,现在可以编写一个通用的First()函数来丢弃第二个(或任何后续的)返回值:

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

这在github.com/icza/gog中可用,作为gog.First()(声明:我是作者)。

使用它:

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

map is different because it is a built-in type and not a function. The 2 forms of accessing an element of a map is specified by the Go Language Specification: Index Expressions and backed by the compiler.

With functions you can't do this. If a function has 2 return values, you have to "expect" both of them or none at all.

However you are allowed to assign any of the return values to the Blank identifier:

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

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

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

You can also choose not to store any of the return values:

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

Note: you could also assign both of the return values to the blank identifier, although it has no use (other than validating that it has exactly 2 return values):

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

You can also try these on the Go Playground.

Helper function

If you use it many times and you don't want to use the blank identifier, create a helper function which discards the 2nd return value:

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

And now you can do:

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

Go 1.18 generics update: Go 1.18 adds generics support, it is now possible to write a generic First() function which discards the second (or any further) return values:

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

This is available in github.com/icza/gog, as gog.First() (disclosure: I'm the author).

Using it:

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

huangapple
  • 本文由 发表于 2015年2月13日 04:21:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/28487036.html
匿名

发表评论

匿名网友

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

确定