【发布时间】:2020-11-04 06:15:29
【问题描述】:
为什么我面临错误,即附加的第一个 arg 必须是在已经断言接口到结构切片之后的切片?
package main
import (
"fmt"
)
type AccessKeys struct {
AccessKeys interface{}
}
type AccessKey struct {
AccessKeyID string
}
func main() {
var b AccessKey
b.AccessKeyID = "ye"
var bs AccessKeys
bs.AccessKeys = bs.AccessKeys.([]AccessKey) // Assert
bs.AccessKeys = append(bs.AccessKeys, b) // Error: first argument to append must be slice; have interface {}
fmt.Println(bs)
}
【问题讨论】:
-
在这里 (
bs.AccessKeys = bs.AccessKeys.([]AccessKey)) 您将其声明为[]AccessKey只是为了将其写回interface{}。基本上这条线什么都不做——除了如果bs.AccessKeys不是[]AccessKey类型时会惊慌失措。很高兴知道您实际上要做什么。使用interface{}在 Go 中应该是一个非常罕见的例外,并且根本不被初学者使用。 -
嘿@TehSphinX,你能说出它为什么会恐慌吗?
-
有两种类型的断言:如果
someVar不是someType类型,b := someVar.(someType)会恐慌。然后是b, ok := someVar.(someType),如果someVar不是someType类型,它将返回ok == false。如果你不能 100% 确定someVar的类型是someType,我会一直使用后者。 -
@TehSphinX 我的意思是为什么上面的例子会恐慌?
interface{}应该能够被断言为几乎任何签名。 -
interface{}下总是有一个底层类型。如果该类型与您断言的类型不同,它将出现恐慌,除非您使用v, ok := ...断言。例如,如果interface{}中有一个string,并且您尝试将其声明为int:var val interface{} = "hello",这将出现恐慌:intVal := val.(int)。请注意,断言不是转换!断言永远不会将变量转换为不同的类型。它只检查现有(基础类型)是否属于 X 类型或实现 X 类型。