简体   繁体   中英

Assert interface to slice of struct

Why am I facing error that first arg to append must be slice after being already asserted interface to a slice of structs?

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)
}

https://play.golang.org/p/OfT3i1AbkMe

It cannot work because you try to append AccessKey to type interface{} which is not a slice.

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 = append(bs.AccessKeys, b)
    
    fmt.Println(bs)
}

But in my opinion this is not very idiomatic way to do something, but depends what are you trying to achieve. What I would even replace

AccessKeys []interface{}
with
AccessKeys []AccessKey

Thanks to a kind poster who deleted his comment later.

It doesn't work because AccessKeys interface{} makes AccessKeys an untyped nil type as the zero value for an interface is untyped nil. As Go is a statically typed language, it will give an error at compile time.

If this makes sense, its for the same reason you can't do this in Go:

n := nil

Even if that is fixed, it will fail at runtime while asserting saying panic: interface conversion: interface {} is nil, not []main.AccessKey . Though I am not sure why.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM