dongliming2416 2016-10-05 11:57
浏览 723

带有指针的Golang类型断言

I've been working in an interface to use as a hierarchical tree. The idea is to aloud the concrete implementations to call .Children(), .Father() and a function to auto populate the hierarchy based on a slice of {id, FatherId} schema.

I only need three different implementations of this interface, maybe it's more convenient to do the whole thing for each struct but I'm new to Go and decided to use this example to understand interfaces.

I've come to an interface that looks something like this:

type Node interface{
    Equals(nodo *Node) bool
    AddChild(child *Node)
    SetFather(father *Node)

    Children() []Node
    Father() *Node
}

So the idea is call a Populate function:

func Populate(plainNodes []Node, HierarchichalNodes *[]Node) {}

Plain nodes would be items defining the id of his father:

{id: "Animal", father: ""}
{id: "Plant", father: ""}
{id: "Mammals", father: "Animal"}

Hierarchical nodes would be the result:

Animal
|__Mammals

Plant

The problem I'm getting is when I try to implement the interface in a concrete struct, this case "Category".

type Category struct{
    children []Category
    father Category
}

func (c Category) SetFather(node *Node) {
    v, ok = node.(*Category)
    c.father = v
}

Notice that in Category I want to work with Category father and children, not with interface Node.

I can't do the conversion, I get :

invalid type assertion: nodo.(*Category) (non-interface type *Node on left)

Any ideas?

  • 写回答

2条回答 默认 最新

  • dry0106 2016-10-05 12:13
    关注

    Your parameter is node *Node, it is of type *Node. Node is an interface type, but *Node is not: it is a pointer to interface.

    Don't use pointer to interface, it is very rarely needed. Instead change it to node Node. Also change all your other *Node pointers to just Node.

    Also if Category.SetFather() method intends to change the Category value identified as the receiver, it must be a pointer else you'd only end up changing a copy which will be discarded after SetFather() returns. So use a receiver like c *Category.

    Going further, if the node argument contains a *Category wrapped in an interface, you can't directly assign it to Category.father as that is a non-pointer type Category. You need a pointer indirection, e.g. c.father = *v; or change the type of the father field to be a pointer: father *Category.

    Corrected SetFather() method could look like this:

    func (c *Category) SetFather(node Node) {
        if v, ok := node.(*Category); ok {
            c.father = *v
        }
    }
    
    评论

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大