使用接口(interface)和动态类型进行变量分配

标签 go

我有一个脚本,它根据用户输入从不同的数据源中提取数据,具有通用界面和每个数据源的类型。然后每个数据源都有一个方法来获取该特定源的元数据。我有点难以理解 idomatic Go 实现根据输入切换类型

这个例子不能编译,但它是最能说明我想做什么的版本:

type Post interface {
  GetMetadata() bool
}

type YouTubeVideo struct {
  ID            string
  Title         string
  ChannelID     string
  ChannelTitle  string
  PublishedAt   string
}

func (ig *YouTubeVideo) GetMetadata() bool {
  // ...
}

type InstagramPic struct {
  ID            string
  ShortCode     string
  Type          string
  Title       string
  PublishedAt   string
}

func (ig *InstagramPic) GetMetadata() bool {
  // ...
}

func main() {
  var thePost Post

  switch domain {
  case "youtube":
    thePost = new(YouTubeVideo)
    thePost.ID = pid
  case "instagram":
    thePost = new(InstagramPic)
    thePost.ShortCode = pid
  }

  thePost.GetMetadata()

  fmt.Println(thePost.title)
}

最佳答案

根据细节,我相信您的结构总体上是合理的。但是需要更多的了解。

使用接口(interface),例如Post,您只能访问为该接口(interface)定义的方法(在本例中为GetMetadata()) .存储在接口(interface)中的值,例如。 *YouTubeVideo*InstagramPic) 不能在没有 type assertion 的情况下访问 type switch .

因此,无法使用thePost.title 获取标题。

获取帖子的字段值

这里有两种选择(如果算上“类型断言”则为三种):

1) 通过接口(interface)方法添加对属性的访问

type Post interface {
  GetMetadata() bool
  Title() string // Added Title method
}

func (ig *YouTubeVideo) Title() string {
  return ig.Title     
}

...

fmt.Println(thePost.Title())

2) 使用类型开关访问属性

switch v := thePost.(type) {
case *YouTubeVideo:
    fmt.Println(v.ChannelTitle)
case *InstagramPic:
    fmt.Println(v.PublishedAt)
}
如果实现 Post 的所有类型也应该提供对特定属性的访问权限,则

备选方案 1) 很有用。 2) 允许您访问特定于该类型的字段,但它需要每种类型的案例。

设置帖子的字段值

就像获取时一样,您不能直接设置接口(interface)值的字段。在您的情况下,您应该先设置所需的字段,然后再将其存储在界面中:

v := new(YouTubeVideo)
v.ID = pid
thePost = v // Store the *YouTubeVideo in thePost

或者更短一点:

thePost = &YouTubeVideo{ID: pid}

最后的说明

通过一些调整,您的结构应该可以使用接口(interface)和类型开关。但具体如何最好地构建它取决于您的具体情况,我们对此知之甚少。

为了更好地理解如何使用界面,我建议阅读: Effective Go: Interfaces and Types

关于使用接口(interface)和动态类型进行变量分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29482343/

相关文章:

regex - 在 Go 中获取正则表达式的解析树

go - Go什么时候分配一个新的后备数组给slice?

在 Golang 中解码为结构的 JSON 标记

转到 ~(波浪字符)目录路径

go - golang http.Get请求按常规方式工作,但在go例程内部不工作

zlib压缩数据时的内存分配?

c++ - GO 中的闭包和局部变量

go - 解析格式为 HHMMSS00 的时间

go - 我可以使用c:= range <string>遍历一个字符串,但仅使用字符而不使用索引吗?

go - 如何在golang中循环嵌套结构?