# 指针

## 陷阱 2：指针指向栈变量的地址逃逸
Go 编译器会自动处理，通常无需担心：

```go
func getPtr() *int {
    v := 10
    return &v  // v 虽然是局部变量，但 Go 会自动提升到堆
}

```

![alt text](image.png)

## 作业: 实现链表节点和基本操作


```go
package main

import "fmt"

type Node struct {
	Value    int
	Previous *Node // 指向前一个节点
	Next     *Node // 指向下一个节点
}

type LinkedList struct {
	Head *Node
}

// TODO: 实现以下方法

// Append 在链表末尾添加节点
func (l *LinkedList) Append(value int) {
	node := &Node{
		Value: value,
	}

	if l.Head == nil {
		l.Head = node
		return
	}

	// 遍历链表找到最后一个节点(没有下一个指向), 然后将新节点添加到末尾
	current := l.Head
	for current.Next != nil {
		current = current.Next
	}

	current.Next = node
	node.Previous = current
}

func (l *LinkedList) Length() int {
	count := 0

	current := l.Head
	for current.Next != nil {
		count++
		current = current.Next
	}
	return count + 1
}

// GetAt 获取指定位置的值
func (l *LinkedList) GetIndexNode(index int) *Node {
	if index < 0 || index >= l.Length() {
		return nil
	}

	current := l.Head
	for range index {
		current = current.Next
	}

	return current
}

// GetAt 获取指定位置的值
func (l *LinkedList) GetAt(index int) (int, bool) {
	current := l.GetIndexNode(index)
	if current == nil {
		return 0, false
	}
	return current.Value, true
}

// Insert 在指定位置插入节点
func (l *LinkedList) Insert(index int, value int) bool {
	node := &Node{
		Value: value,
	}

	// 开始和结束之间的位置
	if index < 0 || index > l.Length() {
		return false
	}

	// // 插入到开头
	// if index == 0 {
	// 	node.Next = l.Head
	// 	l.Head = node
	// 	return true
	// }

	// // 找到索引的前置节点
	// current := l.Head
	// for i := 0; i < index-1; i++ {
	// 	current = current.Next
	// }

	current := l.GetIndexNode(index - 1)

	// 将新节点插入到当前节点和下一个节点之间,
	// 需要把原来的值 挪到后面,
	node.Next = current.Next
	// 把前面的值指向新的节点
	current.Next = node
	return true
}

// Remove 删除指定位置的节点
func (l *LinkedList) Remove(index int) bool {
	if index < 0 || index >= l.Length() {
		return false
	}

	// 删除开头的节点，后面的节点自动升级为新的头节点
	if index == 0 {
		l.Head = l.Head.Next
		return true
	}

	current := l.GetIndexNode(index - 1)

	// 将前一个节点的Next指向要删除节点的下一个节点, 通过Next的Next 来跳过要删除的节点
	current.Next = current.Next.Next
	return true
}

// Print 打印整个链表
func (l *LinkedList) Print() {
	for current := l.Head; current != nil; current = current.Next {
		fmt.Print(current.Value)
		if current.Next != nil {
			fmt.Print(" -> ")
		}
	}
	fmt.Println()
}

func main() {
	list := &LinkedList{}

	list.Append(10)
	list.Append(20)
	list.Append(30)
	list.Print() // 输出: 10 -> 20 -> 30

	list.Insert(1, 15)
	list.Print() // 输出: 10 -> 15 -> 20 -> 30

	value, ok := list.GetAt(2)
	fmt.Println("位置2的值:", value, ok) // 20 true

	list.Remove(1)
	list.Print() // 输出: 10 -> 20 -> 30
	fmt.Println("链表长度:", list.Length())

	fmt.Println(list.GetIndexNode(1).Previous.Value)
}
```