gpt4 book ai didi

go - Go 中联合的最佳实践

转载 作者:IT老高 更新时间:2023-10-28 13:07:17 25 4
gpt4 key购买 nike

Go has no unions .但在许多地方工会是必要的。 XML 过度使用联合或选择类型。我试图找出,这是解决失踪工会的首选方式。例如,我尝试在 XML standard 中为非终端 Misc 编写 Go 代码。可以是 comment , 一个 processing instructionwhite space .

为这三种基本类型编写代码非常简单。它们映射到字符数组和结构。

type Comment Chars

type ProcessingInstruction struct {
Target *Chars
Data *Chars
}

type WhiteSpace Chars

但是当我完成联合的代码时,它变得非常臃肿,包含许多冗余函数。显然必须有一个容器结构。

type Misc struct {
value interface {}
}

为了确保容器只包含三种允许的类型,我将值设为私有(private),并且必须为每种类型编写一个构造函数。

func MiscComment(c *Comment) *Misc {
return &Misc{c}
}

func MiscProcessingInstruction (pi *ProcessingInstruction) *Misc {
return &Misc{pi}
}

func MiscWhiteSpace (ws *WhiteSpace) *Misc {
return &Misc{ws}
}

为了能够测试联合的内容,有必要编写三个谓词:

func (m Misc) IsComment () bool {
_, itis := m.value.(*Comment)
return itis
}

func (m Misc) IsProcessingInstruction () bool {
_, itis := m.value.(*ProcessingInstruction)
return itis
}

func (m Misc) IsWhiteSpace () bool {
_, itis := m.value.(*WhiteSpace)
return itis
}

为了获得正确类型的元素,需要编写三个 getter。

func (m Misc) Comment () *Comment {
return m.value.(*Comment)
}

func (m Misc) ProcessingInstruction () *ProcessingInstruction {
return m.value.(*ProcessingInstruction)
}

func (m Misc) WhiteSpace () *WhiteSpace {
return m.value.(*WhiteSpace)
}

在此之后,我能够创建一个 Misc 类型的数组并使用它:

func main () {

miscs := []*Misc{
MiscComment((*Comment)(NewChars("comment"))),
MiscProcessingInstruction(&ProcessingInstruction{
NewChars("target"),
NewChars("data")}),
MiscWhiteSpace((*WhiteSpace)(NewChars(" \n")))}

for _, misc := range miscs {
if (misc.IsComment()) {
fmt.Println ((*Chars)(misc.Comment()))
} else if (misc.IsProcessingInstruction()) {
fmt.Println (*misc.ProcessingInstruction())
} else if (misc.IsWhiteSpace()) {
fmt.Println ((*Chars)(misc.WhiteSpace()))
} else {
panic ("invalid misc");
}
}
}

您会看到很多代码看起来几乎相同。任何其他工会也是如此。所以我的问题是:有什么方法可以简化 Go 中处理联合的方式?

Go 声称通过 removing redundancy 简化编程工作.但我认为上面的例子正好相反。我错过了什么吗?

这里是完整的例子:http://play.golang.org/p/Zv8rYX-aFr

最佳答案

您似乎是因为想要类型安全而问的,我首先要争辩说您的初始解决方案已经不安全了

func (m Misc) Comment () *Comment {
return m.value.(*Comment)
}

如果您之前没有检查过 IsComment,它会 panic 。因此,该解决方案没有任何好处Volker 提出的类型开关.

由于您想对代码进行分组,您可以编写一个函数来确定 Misc 元素是什么:

func IsMisc(v {}interface) bool {
switch v.(type) {
case Comment: return true
// ...
}
}

然而,这也不会为您带来编译器类型检查。

如果您希望编译器能够将某些内容识别为 Misc,那么您应该考虑创建一个将某些内容标记为 Misc 的接口(interface):

type Misc interface {
ImplementsMisc()
}

type Comment Chars
func (c Comment) ImplementsMisc() {}

type ProcessingInstruction
func (p ProcessingInstruction) ImplementsMisc() {}

这样你就可以编写只处理杂项的函数。对象并稍后决定您真正想要在这些函数中处理的内容(评论、说明、...)。

如果您想模仿联合,那么您编写它的方式就是我所知道的方式。

关于go - Go 中联合的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21553398/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com