【问题标题】:Error addressing the returned slice of a function处理返回的函数切片时出错
【发布时间】:2018-04-27 12:18:55
【问题描述】:

在下一个代码中,第一个 Println 在构建时失败并出现错误 slice of unaddressable value。其余的行都很好。

package main

import "fmt"

func getSlice() [0]int {
   return [...]int{}
}

func getString() string {
   return "hola"
}

func main() {
    fmt.Println(getSlice()[:]) // Error: slice of unaddressable value

    var a = getSlice()
    fmt.Println(a[:])

    fmt.Println(getString()[:])

    var b = getString()
    fmt.Println(b[:])
}

Try this code

如果第一个 Println 被评论,它会起作用。 Try it out

这是为什么呢?我在这里缺少什么?

【问题讨论】:

    标签: string go call slice


    【解决方案1】:

    您缺少的是在对 数组 进行切片时,操作数必须是可寻址的([0]int 是一个数组,而不是切片)。并且函数调用的返回值是不可寻址的。详情见How can I store reference to the result of an operation in Go?;和"cannot take the address of" and "cannot call pointer method on"

    Spec: Slice expressions:

    如果切片操作数是数组,则必须为addressable,切片操作的结果是与数组元素类型相同的切片。

    在这个表达式中:

    getSlice()[:]
    

    getSlice() 返回一个数组,因为它是函数调用的结果,所以它是不可寻址的。因此,您不能对其进行切片。

    在这个表达式中:

    getString()[:]
    

    getString() 返回一个string 值,因此即使该值不可寻址,也可以对其进行切片。这是允许的,因为切片表达式的结果将是另一个 string,而 Go 中的 string 值是不可变的。

    另外,变量是addressable,所以这总是有效的:

    var a = getSlice()
    fmt.Println(a[:])
    

    【讨论】:

      【解决方案2】:

      getSlice() 没有返回一个切片它返回一个数组,这是不可寻址的。你可以返回一个指向数组的指针:

      func getSlice() *[0]int {
         return &[...]int{}
      }
      

      或保留getSlice() 原样并将结果放在临时变量中:

      t := getSlice()
      fmt.Println(t[:])
      

      【讨论】:

      • 你提出的解决方案就是我做的。我不明白为什么它不像字符串那样工作。现在我知道了,谢谢!
      猜你喜欢
      • 1970-01-01
      • 2015-07-06
      • 1970-01-01
      • 2020-01-18
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多