在Go语言中,如何在自定义类型中嵌入其他类型?

huangapple go评论86阅读模式
英文:

In golang, how to embed on custom type?

问题

我有自定义类型Int64ArrayChannelChannelList,如下所示:

type Int64Array []int64

func (ia *Int64Array) Scan(src interface{}) error {
  rawArray := string(src.([]byte))
  if rawArray == "{}" {
    *ia = []int64{}
  } else {
    matches := pgArrayPat.FindStringSubmatch(rawArray)
    if len(matches) > 1 {
      for _, item := range strings.Split(matches[1], ",") {
        i, _ := strconv.ParseInt(item, 10, 64)
        *ia = append(*ia, i)
      }
    }
  }
  return nil
}

func (ia Int64Array) Value() (driver.Value, error) {
  var items []string
  for _, item := range ia {
    items = append(items, strconv.FormatInt(int64(item), 10))
  }
  return fmt.Sprintf("{%s}", strings.Join(items, ",")), nil
}

type Channel int64

type ChannelList []Channel

我该如何将Int64Array嵌入到ChannelList中,以便可以在其上调用ScanValue方法?我尝试了以下代码:

type ChannelList []Channel {
    Int64Array
}

但是我得到了语法错误。重要的是确保ChannelList的项是Channel类型的。如果无法通过嵌入实现这一点,我可以创建独立的函数供ChannelListInt64Array同时调用。

英文:

I have custom types Int64Array, Channel and ChannelList like:

type Int64Array []int64

func (ia *Int64Array) Scan(src interface{}) error {
  rawArray := string(src.([]byte))
  if rawArray == "{}" {
    *ia = []int64{}
  } else {
    matches := pgArrayPat.FindStringSubmatch(rawArray)
    if len(matches) > 1 {
      for _, item := range strings.Split(matches[1], ",") {
        i, _ := strconv.ParseInt(item, 10, 64)
        *ia = append(*ia, i)
      }
    }
  }
  return nil
}

func (ia Int64Array) Value() (driver.Value, error) {
  var items []string
  for _, item := range ia {
    items = append(items, strconv.FormatInt(int64(item), 10))
  }
  return fmt.Sprintf("{%s}", strings.Join(items, ",")), nil
}

type Channel int64

type ChannelList []Channel

How can I embed Int64Array to ChannelList such that I can call Scan and Value methods on it? I tried the following:

type ChannelList []Channel {
    Int64Array
}

but I'm getting syntax error. What's important is to make sure ChannelList items are of type Channel, if this isn't possible via embedding I might just create stand-alone functions to be called by both ChannelList and Int64Array.

答案1

得分: 3

匿名字段(或嵌入字段)出现在结构体中(参见struct类型),而不是类型别名(或“类型声明”)中。

你不能在另一个类型声明中嵌入类型声明。

此外,正如“Go:使用指向数组的指针”的答案所示,你不应该使用指向切片的指针,而应直接使用切片本身(按值传递)。

Wessie评论中友好地指出,(ia *Int64Array) Scan()使用指向切片的指针来改变所引用的底层数组。
我更喜欢返回另一个切片而不是改变现有的切片。
话虽如此,Golang代码审查确实提到:

> 如果接收器是structarrayslice,并且其中任何一个元素是指向可能发生变化的内容的指针,请优先使用指针接收器,因为这将使意图对读者更加清晰。

英文:

An anonymous (or embedded field) is found in a struct (see struct type), not in a type alias (or "type declaration").

You cannot embed a type declaration within another type declaration.

Plus, as illustrated by the answers to "Go: using a pointer to array", you shouldn't be using pointers to slice, use directly the slice themselves (passed by value).

Wessie kindly points out in the comments that (ia *Int64Array) Scan() uses pointer to a slice in order to mutate the underlying array referenced by said slice.
I would prefer returning another slice instead of mutating the existing one.
That being said, the Golang Code Review does mention:

> If the receiver is a struct, array or slice and any of its elements is a pointer to something that might be mutating, prefer a pointer receiver, as it will make the intention more clear to the reader.

huangapple
  • 本文由 发表于 2014年12月30日 17:09:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/27702469.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定