将 nil 分配给指针

Mar*_* DM 3 pointers go

我正在尝试对列表实施 delete() 方法(没有 HEAD ref)

我发现我可以将参数修改为结构体。

func (l *LinkedList) Delete(n *Node) {
    if n.next == nil {
        n = nil
    } else {
        current := &n
        *n = *n.next
        *current = nil
    }

}
Run Code Online (Sandbox Code Playgroud)

“else”部分工作正常,但删除最后一个节点不会修改列表

尝试使用

*n = nil
Run Code Online (Sandbox Code Playgroud)

但后来我有编译错误。

不能在赋值中使用 nil 作为 Node 类型

在这个操场上完成的代码:

http://play.golang.org/p/Dhzyd7QHEw

Klu*_*uyg 5

你只是做错了。我的意思是从单链表中删除经典元素。正确的方法:

func (l *LinkedList) Delete(n *Node) {
    // if we want to delete the head element - just move the head pointer
    if l.head == n {
        l.head = n.next
        return
    }
    // otherwise find previous element to the one we are deleting
    current := l.head
    for current != nil && current.next != n {
        current = current.next
    }
    // and move that previous element next pointer to the next element
    if current != nil {
        current.next = n.next
    }
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/_NlJw_fPWQD

那么你的例子有什么问题?在您的Delete函数中,您会收到一个指向某个节点的指针。这个指针对你的函数来说是局部的,它就像一个局部变量。如果将 nil 分配给函数内的局部变量并不重要。外面 - 没有人会看到这样的任务。您想要做的是更改上一个列表项的下一个指针。这样,该项目将不再出现在列表中。GC 将删除实际分配的内存。

更新:

由于 go 指针是“真实”指针,因此可以通过使用额外的间接级别来实现无需头部移除的特殊情况,正如 Linus 在他著名的TED 演讲中所建议的(以及之前在slashdot Q&A 中- 参见“最喜欢的黑客”)题):

func (l *LinkedList) Delete(n *Node) {
    // initialize indirect with the address of a head pointer
    indirect := &(l.head)
    // until indirect has address of a pointer to the node we're deleting
    for *indirect != n {
        // check that it's not the end of the list
        if (*indirect).next == nil {
            // the node we're tryign to delete is not in the list
            return
        }
        // set indirect to the address of the next pointer
        indirect = &(*indirect).next
    }
    // indirect has address of a pointer we need to modify to delete the node
    *indirect = n.next
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/hDy3hB5LUME

IMO 的两级疏忽比删除 head 元素的简单特例更难理解,但 Linus 并不是像我这样的普通开发人员:)