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

时间:2015-04-07 01:39:33

标签: 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)
}

1 个答案:

答案 0 :(得分:1)

根据细节,我相信您的结构通常是合理的。但需要更多的理解。

使用Post等界面,您只能访问为界面定义的方法(在本例中为GetMetadata())。存储在界面中的值,例如。如果没有 type assertion type switch ,则无法访问*YouTubeVideo*InstagramPic

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

获取帖子的字段值

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

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

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}

最后的注释

通过一些调整,您的结构应该使用接口和类型开关。但究竟如何最好地构建它取决于您的具体情况,我们的信息太少。

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