英文:
Append to slice of interfaces
问题
我正在编写一个文档生成器。其中有一个DocumentItem
接口,它是文档的一部分。
type DocumentItem interface {
compose() string
}
例如,一个文档由段落和表格组成。
type Paragraph struct {
text string
}
type Table struct{}
Paragraph
和Table
类型对应于DocumentItem
接口。
func (p *Paragraph) compose() string {
return ""
}
func (t *Table) compose() string {
return ""
}
Document
类型包含content []*DocumentItem
字段。
type Document struct {
content []*DocumentItem
}
我正在寻找一种方法,使NewParagraph()
和NewTable()
函数能够创建所需的数据类型并将它们添加到content
字段中。
func (d *Document) NewParagraph() *Paragraph {
p := Paragraph{}
d.content = append(d.content, &p)
return &p
}
func (d *Document) NewTable() *Table {
t := Table{}
d.content = append(d.content, &t)
return &t
}
我使用接口指针的切片,以便能够在将它们包含在文档中后修改相应的变量数据。
func (p *Paragraph) SetText(text string) {
p.text = text
}
func main() {
d := Document{}
p := d.NewParagraph()
p.SetText("lalala")
t := d.NewTable()
// ...
}
但是我得到了编译器错误:
cannot use &p (type *Paragraph) as type *DocumentItem in append
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.
type DocumentItem interface {
compose() string
}
For example, a document consists of paragraphs and tables.
type Paragraph struct {
text string
}
type Table struct{}
The Paragraph
and Table
types correspond to the DocumentItem
interface.
func (p *Paragraph) compose() string {
return ""
}
func (t *Table) compose() string {
return ""
}
The Document
type contains the content []*DocumentItem
field.
type Document struct {
content []*DocumentItem
}
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.
func (d *Document) NewParagraph() *Paragraph {
p := Paragraph{}
d.content = append(d.content, &p)
return &p
}
func (d *Document) NewTable() *Table {
t := Table{}
d.content = append(d.content, &t)
return &t
}
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.
func (p *Paragraph) SetText(text string) {
p.text = text
}
func main() {
d := Document{}
p := d.NewParagraph()
p.SetText("lalala")
t := d.NewTable()
// ...
}
But I get compiler errors:
cannot use &p (type *Paragraph) as type *DocumentItem in append
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
不要使用指向接口的指针,只使用接口的切片:
content []DocumentItem
如果接口值中包装的动态值是指针,你不会丢失任何东西,你可以修改指向的对象。
这是唯一需要更改的地方。为了验证,我在最后添加了打印输出:
fmt.Printf("%+v", p)
输出结果(在Go Playground上尝试):
&{text:lalala}
英文:
Don't use pointer to interface, only a slice of interfaces:
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:
fmt.Printf("%+v", p)
Output (try it on the Go Playground):
&{text:lalala}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论