简体   繁体   English

带指针的 Golang 类型断言

[英]Golang type assertion with pointers

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.这个想法是大声调用.Children().Father()的具体实现以及一个基于{id, FatherId}架构切片自动填充层次结构的函数。

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.我只需要这个接口的三个不同的实现,也许为每个结构做整个事情更方便,但我是 Go 的新手,决定使用这个例子来理解接口。

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:所以这个想法是调用一个Populate函数:

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

Plain nodes would be items defining the id of his father:普通节点将是定义他父亲 id 的项目:

{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" .我遇到的问题是当我尝试在具体结构中实现接口时,这种情况下为"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 .请注意,在Category我想与Category父亲和孩子一起工作,而不是与接口Node

I can't do the conversion, I get :我无法进行转换,我得到:

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

Any ideas?有什么想法吗?

Your parameter is node *Node , it is of type *Node .您的参数是node *Node ,它的类型为*Node Node is an interface type, but *Node is not: it is a pointer to interface. Node是一种接口类型,但*Node不是:它是一个指向接口的指针。

Don't use pointer to interface, it is very rarely needed.不要使用指向接口的指针,它很少需要。 Instead change it to node Node .而是将其更改为node Node Also change all your other *Node pointers to just Node .还将所有其他*Node指针更改为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.此外,如果Category.SetFather()方法打算更改标识为接收器的Category值,则它必须是一个指针,否则您最终只会更改在SetFather()返回后将被丢弃的副本。 So use a receiver like c *Category .所以使用像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 .更进一步,如果node参数包含包装在接口中的*Category ,则不能直接将其分配给Category.father因为它是非指针类型Category You need a pointer indirection, eg c.father = *v ;你需要一个指针间接,例如c.father = *v ; or change the type of the father field to be a pointer: father *Category .或将father字段的类型更改为指针: father *Category

Corrected SetFather() method could look like this:更正后的SetFather()方法可能如下所示:

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

This should work:这应该有效:

(*nodo).(Category)

De-reference first, assert afterwards.先取消引用,然后断言。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM