调用struct属性方法时Golang struct指针引用丢失

时间:2018-12-29 08:03:11

标签: pointers go struct

我正在尝试使用struct来管理树上的访问节点。每当我访问父级的子节点的方法时,后续调用中的父级引用都会丢失(即parent.child.method(child) -> [parent becomes nil]-> parent(the previous child).child ... etc)。

这是我文件中的错误摘要。

type Node struct {
    Left *Node
    Right *Node
    value int
}

func (parent *Node) determineSide(child *Node) (Node, Node) {

    if child.Value < parent.Value {
        if parent.hasLeftNode() {
            return parent.Left.determineSide(child)
        }
        return parent.addLeftNode(child)

    } else if child.Value > parent.Value {
        if parent.hasRightNode() {
           return parent.Right.determineSide(child)
        }
        return parent.addRightNode(child)
    }
    return *child, *parent
 }

我试图通过尝试找到一种方法来通知该方法新引用应为parent.Left来解决此问题。使用*parent.Left&parent.Left之类的东西似乎并不正确。

一个解决方案可能是将这段代码移到struct之外,并让另一个函数来处理结果以进行快速修复,但是我想了解为什么此方法无法立即使用。此处的思考过程受this.child.determineSide(child)的影响。

完整代码为here

修改

这是终端的一些输出,可能会提供更多的上下文。看起来我遇到了导致问题的检查类型问题。

parent &{<nil> <nil> 2}
parent.Left <nil>
parent.LeftNode true
child &{<nil> <nil> 1}
parent <nil>
child &{<nil> <nil> 1}

2 个答案:

答案 0 :(得分:1)

好的,我知道你到底要问什么。

New()方法返回一个值,而不是一个指针,这意味着您以后看不到调用者中的更改。调用者得到的只是Node的值副本。因此,您打印的父级将始终为{Left:<nil> Right:<nil> Value:2}

addLeftNode()addRightNode()也是如此。

只使用指针而不是值来实现目标。

请参见pointers_vs_values


我认为这只是问题所在的Visit()方法。

  1. 当您在拜访左孩子后立即返回时,它将永远不会拜访右孩子。
  2. 左子和右子不是互斥的,因此第二个if子句不应使用else if,而应使用if
  3. 访问顺序也有问题。

之前:

// Visit will automatically walk through the Child Nodes of the accessed Parent Node.
func (parent *Node) Visit() (Node, int) {
    fmt.Println("Node value:", parent.Value)
    if parent.hasLeftNode() {
        return parent.Left.Visit()
    } else if parent.hasRightNode() {
        return parent.Right.Visit()
    }
    return *parent, parent.Value
}

已修改:

// Visit will automatically walk through the Child Nodes of the accessed Parent Node.
func (parent *Node) Visit() (Node, int) {
    if parent.hasLeftNode() {
        parent.Left.Visit()
    }
    fmt.Println("Node value:", parent.Value)
    if parent.hasRightNode() {
        parent.Right.Visit()
    }
    return *parent, parent.Value
}

另外,对我来说,Visit()不应返回任何值。

答案 1 :(得分:0)

问题源自错误的类型检查。该函数成功处理了调用,但是我使用的方法在确认是否已分配节点方面并不准确。

// isNode checks whether the provided property is a Node.
func (parent *Node) isNode(property interface{}, typeset interface{}) bool {

   fmt.Println(reflect.TypeOf(property) == reflect.TypeOf(typeset))
   // this always referred to the address for the base Node struct or similar falsy.
   return reflect.TypeOf(property) == reflect.TypeOf(typeset)
}

// hasLeftSide tests whether the Parent Node has a Node assigned to its left side.
func (parent *Node) hasLeftNode() bool {
    return parent.Left != nil //parent.isNode(parent.Left, (*Node)(nil))
}

// hasRightSide tests whether the Parent Node has a Node assigned to its right side.
func (parent *Node) hasRightNode() bool {
    return parent.Right != nil // parent.isNode(parent.Right, (*Node)(nil))
}