【问题标题】:Idiomatic way of representing generic data type in golang在 golang 中表示通用数据类型的惯用方式
【发布时间】:2020-02-16 21:26:17
【问题描述】:

在 AST 的特定实现中,我有一个 node,它是一个接口和 ExprNodeEvalNode 和一些叶节点。现在叶子节点可以是字符串节点或数字节点或函数节点 每个表达式节点只能有两个叶节点。一左一右。

type Node interface{
  Pos() int64
  Typ() NodeType 
}

type StringNode struct{
  Pos int64
  Val string
  Node
}

type NumberNode struct {
  Pos int64
  Val float64
  Node
}

type ExprNode struct {
  Lhs  ???  //should accept either StringNode or NumberNode 
  Op   Operation
  Rhs  ???  //should accept either StringNode or NumberNode 
  Node
}

type EvalNode struct{
  Lhs     *ExprNode
  AllFlag bool
  Rhs     *ExprNode
  Node
}

我想出了一个可能不是惯用的解决方法。我正在寻找是否有更好的方法来做到这一点

type LeafNode interface{
  IsLeaf() bool
}

func (n *StringNode) IsLeaf() bool{
  return true
}

func (n *NumberNode) IsLeaf() bool{
  return true
}

type ExprNode struct {
  Lhs  LeafNode   //workaround
  Op   Operation
  Rhs  LeafNode   //workaround
  Node
}

现在在上述解决方法中,IsLeaf() 函数对我来说没有意义,但我不得不使用它来限制 ExprNode 上接受的节点类型。

如果标题看起来过于宽泛,我们深表歉意。

问题:有没有更好的方法来编写上述场景。

注意:我只是在寻找处理上述场景的惯用方法,而不是寻找算法的替代实现。

【问题讨论】:

  • 在这种情况下使用接口对我来说是惯用的。但界面本身并不完美。我不明白为什么 LhsRhs 不是 Node 类型。稍后您可以使用类型断言或类型开关来获取类型。
  • 我会寻找一些叶节点共有的真正功能;如果没有,尝试为它们建立专用类型/接口似乎没有什么好处。
  • @Adrian 这样想:专用类型不是用于共享相同的特征(功能),而是用于共享相似的属性(字段)。就像可以在一组类型中通用的类型。

标签: go


【解决方案1】:

使用以下类型确保只能将叶子类型分配给 ExprNode.Lhs 和 Exprnode.Rhs:

type Node interface{
  Pos() int64
  Typ() NodeType 
}

type LeafNode interface {
  Node
  Leaf() // sentinel function to distinguish leaf types from other types
}

func (*NumberNode) Leaf() {}
func (*StringNode) Leaf() {}

type ExprNode struct {
  Lhs  LeafNode 
  Op   Operation
  Rhs  LeafNode 
  Node
}

【讨论】:

    猜你喜欢
    • 2012-06-12
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-11
    • 2019-08-03
    相关资源
    最近更新 更多