gpt4 book ai didi

function - golang返回多个值问题

转载 作者:IT老高 更新时间:2023-10-28 13:04:06 24 4
gpt4 key购买 nike

我想知道为什么这是有效的 go 代码:

func FindUserInfo(id string) (Info, bool) {
it, present := all[id]
return it, present
}

但这不是

func FindUserInfo(id string) (Info, bool) {
return all[id]
}

有没有办法避免临时变量?

最佳答案

详细说说我的comment , Effective Go提到访问映射键的多值分配称为“comma ok”模式。

Sometimes you need to distinguish a missing entry from a zero value. Is there an entry for "UTC" or is that the empty string because it's not in the map at all? You can discriminate with a form of multiple assignment.

var seconds int
var ok bool
seconds, ok = timeZone[tz]

For obvious reasons this is called the “comma ok” idiom. In this example, if tz is present, seconds will be set appropriately and ok will be true; if not, seconds will be set to zero and ok will be false.

Playground demonstrating this

我们可以看到,这与调用常规函数不同,编译器会告诉你有问题:

package main

import "fmt"

func multiValueReturn() (int, int) {
return 0, 0
}

func main() {
fmt.Println(multiValueReturn)

asgn1, _ := multiValueReturn()

asgn2 := multiValueReturn()
}

playground这将输出

# command-line-arguments
/tmp/sandbox592492597/main.go:14: multiple-value multiValueReturn() in single-value context

这给了我们一个提示,它可能是编译器正在做的事情。 Searching the source code for "commaOk"为我们提供了一些可以查看的地方,包括 types.unpack

在写这篇文章的时候,方法的 godoc 是这样写的:

// unpack takes a getter get and a number of operands n. If n == 1, unpack
// calls the incoming getter for the first operand. If that operand is
// invalid, unpack returns (nil, 0, false). Otherwise, if that operand is a
// function call, or a comma-ok expression and allowCommaOk is set, the result
// is a new getter and operand count providing access to the function results,
// or comma-ok values, respectively. The third result value reports if it
// is indeed the comma-ok case. In all other cases, the incoming getter and
// operand count are returned unchanged, and the third result value is false.
//
// In other words, if there's exactly one operand that - after type-checking
// by calling get - stands for multiple operands, the resulting getter provides
// access to those operands instead.
//
// If the returned getter is called at most once for a given operand index i
// (including i == 0), that operand is guaranteed to cause only one call of
// the incoming getter with that i.
//

这个方法的关键在于该方法似乎可以确定某事是否实际上是“逗号正常”的情况。

深入研究该方法告诉我们,它将检查操作数的模式是否是索引 map 或模式是否设置为 commaok(这里is defined 确实为我们提供了很多关于何时使用它的提示,但是搜索 commaok 的分配源我们可以看到它在 getting a value from a channeltype assertions 时使用)。以后记得加粗部分!

if x0.mode == mapindex || x0.mode == commaok {
// comma-ok value
if allowCommaOk {
a := [2]Type{x0.typ, Typ[UntypedBool]}
return func(x *operand, i int) {
x.mode = value
x.expr = x0.expr
x.typ = a[i]
}, 2, true
}
x0.mode = value
}

allowCommaOk 是函数的参数。检查在该文件中调用 unpack 的位置,我们可以看到所有调用者都将 false 作为参数传递。搜索存储库的其余部分会导致我们找到 Checker.initVars() method 中的 assignments.go .

l := len(lhs)
get, r, commaOk := unpack(func(x *operand, i int) { check.expr(x, rhs[i]) }, len(rhs), l == 2 && !returnPos.IsValid())

因为在进行多值赋值时,我们似乎只能使用“comma ok”模式来获得两个返回值,这看起来是正确的地方!在上面的代码中,检查了左侧的长度,当调用 unpack 时,allowCommaOk 参数是 l == 2 && !returnPos 的结果.IsValid()!returnPos.IsValid() 在这里有点令人困惑,因为这意味着位置 has no file or line information associated有它,但我们会忽略它。

在我们得到的那个方法中更进一步:

var x operand
if commaOk {
var a [2]Type
for i := range a {
get(&x, i)
a[i] = check.initVar(lhs[i], &x, returnPos.IsValid())
}
check.recordCommaOkTypes(rhs[0], a)
return
}

那么这一切告诉我们什么?

  • 由于 unpack 方法采用 allowCommaOk 参数,该参数在 assignment.go 中的所有位置都被硬编码为 false except' s Checker.initVars() 方法,我们可以假设你在赋值时只会得到两个值,并且左侧有两个变量。
  • unpack 方法将通过检查您是否正在索引 slice 来确定您是否真正确实 得到一个 ok 值,从 channel 中获取值,或进行类型断言
  • 由于您只能在进行赋值时获得 ok 值,因此在您的特定情况下,您将始终需要使用变量

关于function - golang返回多个值问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30129206/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com