Go:为新旧变量分配多个返回值函数

时间:2014-08-01 15:08:10

标签: go

在go中有返回两个值或更多值的函数,通常一个是错误。假设我想将第一个返回值存储到已经初始化的变量中,但我想初始化变量以包含内联错误。有没有办法做到这一点?

例如,假设我有这段代码

var a int
//This code doesn't compile because err doesn't exist
a, err = SomeFuncWithTwoReturnValues()
//This code doesn't compile either
a, err := SomeFuncWithTwoReturnValues()

我知道你可以这样做,但我希望有一种方法可以全部内联

var a int
var err error
a, err = SomeFuncWithTwoReturnValues()

a, err := SomeFuncWithTwoReturnValues()
编辑:上面的代码实际编译,所以我回顾了我的代码以深入挖掘更多并创建了一个实际复制问题的快速示例(不仅仅是在我的脑海中......)。

package main

func myfunc() (int, int) {
    return 1, 1
}

func main() {
    a := make([]int, 1)
    a[0], b := myfunc()
    a[0] = b
}

编译器说main.go|9| non-name a[0] on left side of :=。如果我将其设为=而不是:=,则永远不会创建b。我觉得虽然没有简写的方法。

3 个答案:

答案 0 :(得分:4)

正如您在评论中提到的那样,您需要使用=运算符才能分配您已声明的变量。 :=运算符用于同时声明和赋值变量。两者是相同的:

var x int
x = 5
//is the same as
x := 5

此解决方案至少会编译:

package main

func myfunc() (int, int) {
    return 1, 1
}

func main() {
    var b int
    a := make([]int, 1)
    a[0], b = myfunc()
    a[0] = b
}

要回答您的问题,我认为在返回多个值时,无法同时使用未声明和声明的变量。这将尝试同时使用两个不同的运算符。

编辑:刚刚从编译的代码中看到了您的示例,因此您似乎已经熟悉了go的赋值运算符。无论如何,我会留下这个例子。

答案 1 :(得分:3)

Golang不是一种非常一致的语言。这是一个很好的例子。刚开始我很困惑,如果他们总是允许:=运算符,那会容易得多。编译器足够聪明,可以检测已经声明的变量:

package main

import "fmt"

func testFunc() (int,error) {
   return 42,fmt.Errorf("Test Error")
}

func main() {
   number1,err := testFunc() // OK
   number2,err := testFunc() // OK, even if err is already defined
   number1,err = testFunc()  // OK
   // number1,err := testFunc() // ERROR: no new variables on left side of :=

   fmt.Println(number1,number2,err)
}

游乐场链接:https://play.golang.org/p/eZVB-kG6RtX

这是不一致的,因为golang允许您在已声明的变量中使用:=,如果您为其分配了变量,同时还引入了一个新变量。因此,编译器可以检测到变量已存在,并跳过其声明。但是,golang开发人员决定仅在您引入至少一个新价值时才允许这样做。最后一个例子表明了这一点。

答案 2 :(得分:0)

我遇到过这样的情况:

package main
import "os"

func main() {
   var cache struct { dir string }
   // undefined: err
   cache.dir, err = os.UserCacheDir()
   // non-name cache.dir on left side of :=
   cache.dir, err := os.UserCacheDir()
   if err != nil {
      panic(err)
   }
   println(cache.dir)
}

正如您所发现的,这个问题没有一个干净的解决方案。你可以声明 一个额外的变量:

dir, err := os.UserCacheDir()
if err != nil {
   panic(err)
}
cache := userCache{dir}

或者,虽然更详细,但您可以事先声明错误。这样可以省 内存,因为 Go 不使用 Rust 所有权模型:

var (
   cache struct { dir string }
   err error
)
cache.dir, err = os.UserCacheDir()