Ссылка на указатель на структуру Golang потеряна при вызове метода свойства структуры - PullRequest
0 голосов
/ 29 декабря 2018

Я пытаюсь использовать 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).

Полный код здесь .

Редактировать

Вот некоторыевывод из терминала, который может дать еще больший контекст.Похоже, у меня проблема с типом чека, ведущая к проблеме.

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

Ответы [ 2 ]

0 голосов
/ 29 декабря 2018

Проблема возникла из-за неправильной проверки типа.Функция успешно обработала вызов, но метод, который я использовал, не дал точного подтверждения, был ли назначен узел.

// 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))
}
0 голосов
/ 29 декабря 2018

Ладно. Я знаю, что вы точно спрашиваете в конце концов.

New() методы возвращают значение, а не указатель, что означает, что вы не можете видеть более поздние изменения в вызывающей программе.То, что получил вызывающий объект, является только ценностной копией узла.Таким образом, родительский результат всегда будет {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() не должно возвращать никаких значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...