如何在Golang中使用指针实现双向链表_Golang双链表节点操作

3次阅读

双向链表节点必须用指针定义,因为go结构体值传递会导致复制后指针失效;正确定义为type node Struct{Data int; Next, Prev Node}和type DoublyLinkedList struct{Head, Tail Node; Size int}。

如何在Golang中使用指针实现双向链表_Golang双链表节点操作

为什么双向链表的节点必须用指针定义

Go 语言中,结构体默认按值传递。如果 Node 是普通结构体类型,每次插入、删除或遍历时复制整个节点(含前后指针和数据),不仅浪费内存,更会导致 nextprev 指向失效——因为复制后的新节点指针仍指向旧地址,而原节点可能已被回收或移动。
所以必须用指针类型*Node,确保所有操作都作用于同一块内存上的节点实例。

如何正确定义双向链表节点和链表结构

节点需包含数据字段、nextprev 两个 *Node 字段;链表结构体通常只保留头尾指针和长度,避免冗余状态。
常见错误是把 next/prev 定义为 Node(非指针),或在链表结构里存了重复的 head/tail 且未同步更新。

type Node struct {     Data int     Next *Node     Prev *Node }  type DoublyLinkedList struct {     Head *Node     Tail *Node     Size int }

插入节点时最容易漏掉的双向链接步骤

插入不是单向“连上一个”,而是要同时修正四个指针:新节点的 Next/Prev,以及它左右邻居的对应指针。尤其在头插/尾插时,容易忘记更新 HeadTail 的指向,或漏掉对空链表的特殊处理。

  • 头插:新节点 Next = list.Head,若原 Head != nilHead.Prev = newNode;最后 list.Head = newNode
  • 尾插:新节点 Prev = list.Tail,若原 Tail != nilTail.Next = newNode;最后 list.Tail = newNode
  • 中间插入(如在 target 后):设 newNode.Next = target.NextnewNode.Prev = target,再更新 target.Next.Prev = newNodetarget.Next = newNode

遍历和删除时的空指针 panic 风险点

Go 运行时报 panic: runtime Error: invalid memory address or nil pointer dereference 很大概率出现在遍历或删除逻辑里——比如没检查 current != nil 就直接访问 current.Next,或删除唯一节点后未将 HeadTail 同时置为 nil

立即学习go语言免费学习笔记(深入)”;

  • 正向遍历必须写成:for current := list.Head; current != nil; current = current.Next
  • 删除节点前,先判断是否为头/尾节点,并分别处理:if node == list.Head → 更新 list.Head = node.Next;若新 Head 不为空,还要 Head.Prev = nil
  • 删除后务必手动置空已释放节点的指针字段(非必需但利于调试):node.Next, node.Prev = nil, nil

实际写法中,最常被忽略的是「删除后未同步更新链表的 Size」和「在多 goroutine 场景下未加锁」——这两个不导致编译失败,但会让行为变得不可预测。

text=ZqhQzanResources