追加到接口切片

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

Append to slice of interfaces

问题

我正在编写一个文档生成器。其中有一个DocumentItem接口,它是文档的一部分。

  1. type DocumentItem interface {
  2. compose() string
  3. }

例如,一个文档由段落和表格组成。

  1. type Paragraph struct {
  2. text string
  3. }
  4. type Table struct{}

ParagraphTable类型对应于DocumentItem接口。

  1. func (p *Paragraph) compose() string {
  2. return ""
  3. }
  4. func (t *Table) compose() string {
  5. return ""
  6. }

Document类型包含content []*DocumentItem字段。

  1. type Document struct {
  2. content []*DocumentItem
  3. }

我正在寻找一种方法,使NewParagraph()NewTable()函数能够创建所需的数据类型并将它们添加到content字段中。

  1. func (d *Document) NewParagraph() *Paragraph {
  2. p := Paragraph{}
  3. d.content = append(d.content, &p)
  4. return &p
  5. }
  6. func (d *Document) NewTable() *Table {
  7. t := Table{}
  8. d.content = append(d.content, &t)
  9. return &t
  10. }

我使用接口指针的切片,以便能够在将它们包含在文档中后修改相应的变量数据。

  1. func (p *Paragraph) SetText(text string) {
  2. p.text = text
  3. }
  4. func main() {
  5. d := Document{}
  6. p := d.NewParagraph()
  7. p.SetText("lalala")
  8. t := d.NewTable()
  9. // ...
  10. }

但是我得到了编译器错误:

  1. cannot use &p (type *Paragraph) as type *DocumentItem in append
  2. cannot use &t (type *Table) as type *DocumentItem in append

如果我将类型转换为DocumentItem接口,我将失去对特定函数的访问权限,而这些函数在某些类型的情况下可能与其他类型不同。例如,对于段落,可以添加文本,对于表格,可以添加一行单元格,然后对单元格添加文本。

这种情况是否可能?

英文:

I'm writing a document generator. There is a DocumentItem interface - this is part of the document.

  1. type DocumentItem interface {
  2. compose() string
  3. }

For example, a document consists of paragraphs and tables.

  1. type Paragraph struct {
  2. text string
  3. }
  4. type Table struct{}

The Paragraph and Table types correspond to the DocumentItem interface.

  1. func (p *Paragraph) compose() string {
  2. return ""
  3. }
  4. func (t *Table) compose() string {
  5. return ""
  6. }

The Document type contains the content []*DocumentItem field.

  1. type Document struct {
  2. content []*DocumentItem
  3. }

I'm looking for a way that would allow NewParagraph() and NewTable() functions to create the necessary data types and add them to the content field.

  1. func (d *Document) NewParagraph() *Paragraph {
  2. p := Paragraph{}
  3. d.content = append(d.content, &p)
  4. return &p
  5. }
  6. func (d *Document) NewTable() *Table {
  7. t := Table{}
  8. d.content = append(d.content, &t)
  9. return &t
  10. }

I use an slice of interface pointers in order to be able to modify the data in the corresponding variables after they are included in the document.

  1. func (p *Paragraph) SetText(text string) {
  2. p.text = text
  3. }
  4. func main() {
  5. d := Document{}
  6. p := d.NewParagraph()
  7. p.SetText("lalala")
  8. t := d.NewTable()
  9. // ...
  10. }

But I get compiler errors:

  1. cannot use &p (type *Paragraph) as type *DocumentItem in append
  2. cannot use &t (type *Table) as type *DocumentItem in append

If I cast the types to an DocumentItem interface, I will lose access to specific functions, which in the case of one type may differ from the other. For example, add text to a paragraph and add a row of cells and then add text to cell for the table.

Is it possible at all?

Full example at https://play.golang.org/p/uJfKs5tJ98

答案1

得分: 4

不要使用指向接口的指针,只使用接口的切片:

  1. content []DocumentItem

如果接口值中包装的动态值是指针,你不会丢失任何东西,你可以修改指向的对象。

这是唯一需要更改的地方。为了验证,我在最后添加了打印输出:

  1. fmt.Printf("%+v", p)

输出结果(在Go Playground上尝试):

  1. &{text:lalala}
英文:

Don't use pointer to interface, only a slice of interfaces:

  1. content []DocumentItem

If the dynamic value wrapped in the interface value is a pointer, you lose nothing, you will be able to modify the pointed object.

This was the only thing that had to be changed. To verify, I added printing at the end:

  1. fmt.Printf("%+v", p)

Output (try it on the Go Playground):

  1. &{text:lalala}

huangapple
  • 本文由 发表于 2017年4月25日 18:16:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/43607857.html
匿名

发表评论

匿名网友

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

确定