【问题标题】:Assert interface to slice of struct断言结构切片的接口
【发布时间】: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)
}

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

【问题讨论】:

  • 在这里 (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,并且您尝试将其声明为intvar val interface{} = "hello",这将出现恐慌:intVal := val.(int)。请注意,断言不是转换!断言永远不会将变量转换为不同的类型。它只检查现有(基础类型)是否属于 X 类型或实现 X 类型。

标签: go interface


【解决方案1】:

它无法工作,因为您尝试将 AccessKey 附加到不是切片的类型 interface{}。

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

但在我看来,这不是非常惯用的做某事的方式,而是取决于你想要实现什么。我什至会替换什么

AccessKeys []接口{}

访问密钥 []访问密钥

【讨论】:

    【解决方案2】:

    感谢后来删除评论的好心发帖者。

    它不起作用,因为AccessKeys interface{} 使 AccessKeys 成为 untyped nil 类型,因为接口的零值是 untyped nil。由于 Go 是一种静态类型语言,它会在编译时报错。

    如果这是有道理的,出于同样的原因,你不能在 Go 中这样做:

    n := nil
    

    即使已修复,它也会在运行时失败,同时断言 panic: interface conversion: interface {} is nil, not []main.AccessKey。虽然我不知道为什么。

    【讨论】:

      猜你喜欢
      • 2012-10-11
      • 2012-02-25
      • 2020-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-21
      相关资源
      最近更新 更多