【问题标题】:Map of types in Golang?Golang中的类型图?
【发布时间】:2021-09-29 13:42:19
【问题描述】:

我正在为已知由几种特定类型的帧组成的音频/视频流编写解析器。每个帧类型都有自己的子标题格式,因此我为每个帧类型定义了一个结构类型,以将它们用于作为第三个参数传递给binary.Read 的变量:

type TypeVideoIHeader struct {
    MType       byte // type of media e.g. H.264
    FPS         byte
    Width       byte
    Height      byte
    DateTime    int32
    Length      int32
}

type TypeVideoPHeader struct {
    Length      int32
}

type TypeAudioHeader struct {
    MType       byte
    SampleRate  byte
    Length      int16
}

帧的类型是由其头部中的某个字节定义的,所以我将它们放入常量中:

type FrameType byte

const (
    VideoI  FrameType = 0xFC
    VideoP  FrameType = 0xFD
    Audio   FrameType = 0xFA
)

现在,在我可以调用binary.Read之前我必须创建一个正确类型的变量(上面的 3 个结构之一),函数将用流中的值填充该变量。 p>

如何仅通过 FrameType 变量初始化正确类型的变量?有没有简洁优雅的解决方案?

说这种伎俩是否可行:

TMap := map[FrameType]type{
    VideoI: TypeVideoIHeader,
    VideoP: TypeVideoPHeader,
    Audio: TypeAudioHeader,
}

var videoISubHeader TMap[VideoI]

——这就是我所追求的。

【问题讨论】:

  • 你需要的是polymorphism;接口(很快,泛型)在 Go 中启用多态性。只需声明所有三种结构类型都满足的接口类型;然后将该接口类型用作地图的值类型。
  • @jub0bs 看起来接口定义了功能契约,但我的示例中的结构没有功能。
  • 那你可以使用空接口(@98​​7654329@)或者给自己一个所谓的marker interface

标签: dictionary go types


【解决方案1】:
TMap := map[FrameType]func() interface{} {
    VideoI: func() interface{} { return &TypeVideoIHeader{} },
    VideoP: func() interface{} { return &TypeVideoPHeader{} },
    Audio:  func() interface{} { return &TypeAudioHeader{} },
}

var videoISubHeader = TMap[VideoI]()

if err := binary.Read(r, order, videoISubHeader); err != nil {
    panic(err)
}

注意binary.Read 期望第三个参数是一个指针,否则它将无法将二进制数据读入传入的变量中,这就是函数使用& 的原因。

【讨论】:

  • 读操作后,videoISubHeader 仍然是interface{}。如何访问属性Length,所有 3 结构类型都通用?使用类型断言进行猜测。所以我们又回到了起点:如何通过VideoI 断言正确的类型?
  • @Greendrake 类型断言,或者,您可以使用 getter 方法声明接口类型,在所有标头类型上实现这些方法,然后在 TMap 定义中将 interface{} 类型替换为新的非空接口类型。
  • @Greendrake 请注意,您所希望的在 Go 中是不可能的,至少目前不可能,也许在 2022 年计划添加泛型的某个时候,您将能够更接近你的目标,但目前你必须满足于界面。
  • @Greendrake 还有一件事,如果你没有创建接口类型的意图,那么你可以使用反射来访问struct fields by name。通常不鼓励反思,但如果这是您需要的,那么您应该使用它。
猜你喜欢
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 2019-05-18
  • 2014-01-22
  • 2018-12-06
  • 2017-02-22
  • 2016-02-27
  • 2015-06-02
相关资源
最近更新 更多