在下一个代码中,第一个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[:])
}
如果第一个Println
被评论,则可行。
Try it out
为什么?我在这里缺少什么?
答案 0 :(得分:3)
您缺少的是切片数组时,操作数必须是可寻址的([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"。
如果切片操作数是一个数组,则它必须是addressable,并且切片操作的结果是一个与数组具有相同元素类型的切片。
在这个表达式中:
getSlice()[:]
getSlice()
会返回数组,因为它是函数调用的结果,所以它不可寻址。因此你无法切片。
在这个表达式中:
getString()[:]
getString()
返回string
值,因此即使该值不可寻址也可以进行切片。这是允许的,因为切片表达式的结果将是另一个string
,并且Go中的string
值是不可变的。
此外,变量为addressable,因此这将始终有效:
var a = getSlice()
fmt.Println(a[:])
答案 1 :(得分:1)
getSlice()
没有返回一个切片,它返回一个不可寻址的数组。您可以返回指向数组的指针:
func getSlice() *[0]int {
return &[...]int{}
}
或保留getSlice()
,并将结果放在临时变量中:
t := getSlice()
fmt.Println(t[:])