首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Go中工会的最佳做法

Go中工会的最佳做法
EN

Stack Overflow用户
提问于 2014-02-04 13:06:22
回答 4查看 13.9K关注 0票数 18

Go没有工会。但在许多地方,工会是必要的。XML过度使用联合或选择类型。我试着找出答案,这是解决工会问题的首选方法。例如,我试图为XML标准中的非终端XML标准编写Go代码,该代码可以是评论处理指令空白区

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

代码语言:javascript
复制
type Comment Chars

type ProcessingInstruction struct {
    Target *Chars
    Data *Chars
}

type WhiteSpace Chars

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

代码语言:javascript
复制
type Misc struct {
    value interface {}
}

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

代码语言:javascript
复制
func MiscComment(c *Comment) *Misc {
    return &Misc{c}
}

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

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

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

代码语言:javascript
复制
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。

代码语言:javascript
复制
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类型数组并使用它:

代码语言:javascript
复制
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声称简化了消除冗余的编程工作。但我认为上面的例子正好相反。我错过什么了吗?

下面是完整的示例:http://play.golang.org/p/Zv8rYX-aFr

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-02-05 01:43:26

就像你要求的那样,因为你想要类型安全,我首先要说的是你最初的解决方案已经不安全了

代码语言:javascript
复制
func (m Misc) Comment () *Comment {
    return m.value.(*Comment)
}

如果您以前没有检查过IsComment,这将引起恐慌。因此,该解决方案与沃尔克提出的类型切换相比没有任何好处。

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

代码语言:javascript
复制
func IsMisc(v {}interface) bool {
    switch v.(type) {
        case Comment: return true
        // ...
    }
}

但是,这也不会给您带来编译器类型检查。

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

代码语言:javascript
复制
type Misc interface {
    ImplementsMisc()
}

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

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

这样,您就可以编写只处理misc的函数。对象,然后再决定真正要处理的内容(注释、说明、.)。在这些职能中。

如果你想模仿工会,那么你的写作方式就是我所知道的。

票数 13
EN

Stack Overflow用户

发布于 2014-02-04 14:20:30

我认为这样的代码数量可能会减少,例如,我个人并不认为保护type Misc不包含“非法”的东西真的有帮助:一个简单的type Misc interface{}就可以了,或者呢?

这样,就可以节省构造函数和所有Is{Comment,ProcessingInstruction,WhiteSpace}方法,从而简化为类型切换。

代码语言:javascript
复制
switch m := misc.(type) {
    Comment: fmt.Println(m)
    ... 
    default: panic()
}

这就是包编码/xml对令牌所做的事情。

票数 6
EN

Stack Overflow用户

发布于 2014-02-04 23:34:23

我不太明白你的问题。这样做的‘容易’方式将类似于带有接口{}的编码/xml包。如果您不想使用接口,那么您可以像以前那样做一些事情。但是,正如您所说的,Go是一种类型化语言,因此应该用于类型化需求。如果您有一个结构化XML,Go可能是一个很好的选择,但是您需要编写您的模式。如果您想要一个多样化的模式(一个给定的字段可以有多个类型),那么使用非类型化语言可能会更好。

对于json来说非常有用的工具,可以很容易地为xml:http://mholt.github.io/json-to-go/重写。

给出一个json输入,它给出确切的Go结构。您可以有多个类型,但您需要知道哪个字段具有什么类型。如果你不这样做,你需要使用反射,实际上你失去了很多的兴趣去。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21553398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档