<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>anh&apos;s blog</title><description>记录生活与技术笔记</description><link>https://fuwari.vercel.app/</link><language>zh_CN</language><item><title>260715GO数组</title><link>https://fuwari.vercel.app/posts/260715go%E6%95%B0%E7%BB%84/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/260715go%E6%95%B0%E7%BB%84/</guid><description>数组（顺序存储）基本原理</description><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;数组（顺序存储）基本原理&lt;/h1&gt;
&lt;h2&gt;一、数组两大分类&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;静态数组&lt;/strong&gt;：原始形态，是一块&lt;strong&gt;固定长度、连续的内存空间&lt;/strong&gt;，依靠索引直接访问内存。长度初始化后不可改变。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态数组&lt;/strong&gt;：基于静态数组封装而来，内置 &lt;code&gt;push&lt;/code&gt;、&lt;code&gt;insert&lt;/code&gt;、&lt;code&gt;remove&lt;/code&gt; 等常用 API，可自动完成扩容/缩容，简化增删操作。
&lt;ul&gt;
&lt;li&gt;后续栈、队列、哈希表等很多数据结构底层都依赖动态数组实现&lt;/li&gt;
&lt;li&gt;算法刷题和开发日常一般直接使用动态数组（Go 的 slice），静态数组多用于理解底层原理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Go 静态数组定义&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// 定义长度固定为 10 的 int 静态数组
var arr [10]int
// 索引赋值
arr[0] = 1
arr[1] = 2
// 索引取值
a := arr[0]
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;核心特性：&lt;strong&gt;随机访问&lt;/strong&gt; — 通过索引可 O(1) 时间直接读取/修改对应元素&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;二、静态数组：增删原理 &amp;amp; 时间复杂度&lt;/h2&gt;
&lt;h3&gt;1. 新增元素&lt;/h3&gt;
&lt;h4&gt;情况1：末尾追加（有空闲空间）&lt;/h4&gt;
&lt;p&gt;直接对末尾空位索引赋值，无需移动元素&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var arr [10]int
// 前4个位置存入元素
for i := 0; i &amp;lt; 4; i++ {
    arr[i] = i
}
// 末尾追加元素
arr[4] = 4
arr[5] = 5
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;时间复杂度：&lt;strong&gt;O(1)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;情况2：中间插入（有空闲空间）&lt;/h4&gt;
&lt;p&gt;需要把插入位置及之后的原有元素&lt;strong&gt;向后整体搬移一位&lt;/strong&gt;（倒序遍历防止数据覆盖），腾出空位后插入新元素&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

func main() {
    var arr [10]int
    for i := 0; i &amp;lt; 4; i++ {
        arr[i] = i
    }
    // 在索引 2 插入元素 666，后移后续元素
    for i := 4; i &amp;gt; 2; i-- {
        arr[i] = arr[i-1]
    }
    arr[2] = 666
    fmt.Println(arr)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;时间复杂度：&lt;strong&gt;O(N)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;情况3：数组空间已满&lt;/h4&gt;
&lt;p&gt;需要手动&lt;strong&gt;扩容&lt;/strong&gt;：新建一块更大的静态数组，复制原有全部数据，再进行新增操作&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 原数组已满
arr := make([]int, 10)
for i := 0; i &amp;lt; 10; i++ {
    arr[i] = i
}
// 创建更大数组并复制原数据
newArr := make([]int, 20)
for i := 0; i &amp;lt; 10; i++ {
    newArr[i] = arr[i]
}
// 在新数组末尾追加元素
newArr[10] = 10
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;扩容涉及全量拷贝，单次扩容操作复杂度：&lt;strong&gt;O(N)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 删除元素&lt;/h3&gt;
&lt;h4&gt;情况1：删除末尾元素&lt;/h4&gt;
&lt;p&gt;直接标记/截断末尾元素，无需搬移数据&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var arr [10]int
for i := 0; i &amp;lt; 5; i++ {
    arr[i] = i
}
// 删除末尾元素（示例标记为-1）
arr[4] = -1
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;时间复杂度：&lt;strong&gt;O(1)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;情况2：删除中间元素&lt;/h4&gt;
&lt;p&gt;把被删元素后面的元素&lt;strong&gt;整体向前搬移一位&lt;/strong&gt;（正序遍历），保持数组连续性&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var arr [10]int
for i := 0; i &amp;lt; 5; i++ {
    arr[i] = i
}
// 删除索引1的元素，后续元素前移
for i := 1; i &amp;lt; 4; i++ {
    arr[i] = arr[i + 1]
}
arr[4] = -1
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;时间复杂度：&lt;strong&gt;O(N)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 查 &amp;amp; 改&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;按索引查询元素：O(1)&lt;/li&gt;
&lt;li&gt;按索引修改元素：O(1)&lt;/li&gt;
&lt;li&gt;按元素值遍历查找（非索引查找）：O(N)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 静态数组复杂度总览&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;增
&lt;ul&gt;
&lt;li&gt;末尾追加（有空位）：O(1)&lt;/li&gt;
&lt;li&gt;中间插入：O(N)&lt;/li&gt;
&lt;li&gt;满数组扩容新增：O(N)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;删
&lt;ul&gt;
&lt;li&gt;删除末尾元素：O(1)&lt;/li&gt;
&lt;li&gt;删除中间元素：O(N)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;查（索引访问）：O(1)&lt;/li&gt;
&lt;li&gt;改（索引修改）：O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;三、动态数组（Go Slice）用法&lt;/h2&gt;
&lt;p&gt;底层依旧依托静态数组，自动处理扩容、缩容和数据搬移，对外提供简洁 API&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

func main() {
    // 创建初始长度为0的动态数组
    arr := make([]int, 0)

    // 末尾追加元素
    for i := 0; i &amp;lt; 10; i++ {
        arr = append(arr, i)
    }

    // 在索引 2 插入元素 666
    arr = append(arr[:2], append([]int{666}, arr[2:]...)...)

    // 在头部插入元素 -1
    arr = append([]int{-1}, arr...)

    // 删除末尾元素
    arr = arr[:len(arr)-1]

    // 删除索引 2 的元素
    arr = append(arr[:2], arr[3:]...)

    // 索引查询
    a := arr[0]
    fmt.Println(a)

    // 索引修改
    arr[0] = 100

    // 根据值查找索引（遍历查找，复杂度 O(N)）
    index := -1
    for i, v := range arr {
        if v == 666 {
            index = i
            break
        }
    }
    fmt.Println(&quot;666的索引：&quot;, index)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;四、核心特点总结&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;✅ 优点：支持索引随机访问，末尾增删效率极高（O(1)），结构简单&lt;/li&gt;
&lt;li&gt;❌ 缺点：中间位置增删效率差（O(N)），会产生大量数据搬移；静态数组长度固定不够灵活&lt;/li&gt;
&lt;li&gt;底层本质：连续内存存储，动态数组 = 静态数组 + 自动扩容/缩容 + 封装增删API&lt;/li&gt;
&lt;li&gt;适用场景：读多写少、主要在尾部增删、频繁按索引随机访问的场景；不适合频繁在数组中间插入删除的场景&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>260715GO算法题常用技巧</title><link>https://fuwari.vercel.app/posts/260715go%E7%AE%97%E6%B3%95%E9%A2%98%E5%B8%B8%E7%94%A8%E6%8A%80%E5%B7%A7/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/260715go%E7%AE%97%E6%B3%95%E9%A2%98%E5%B8%B8%E7%94%A8%E6%8A%80%E5%B7%A7/</guid><description>GO算法题常用技巧</description><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;GO 算法题常用技巧 &amp;amp; ACM模式模板笔记&lt;/h1&gt;
&lt;h2&gt;一、ACM 模式 I/O 模板&lt;/h2&gt;
&lt;p&gt;很多 OJ 平台使用 ACM 模式，需要自行处理输入输出&lt;/p&gt;
&lt;h3&gt;1. fmt.Scan 基础模板&lt;/h3&gt;
&lt;p&gt;fmt.Scan 会自动跳过空白字符（空格、换行、制表符），逐个读取数据，&lt;strong&gt;参数必须传指针（加 &amp;amp;）&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import &quot;fmt&quot;

func main() {
    var n int
    fmt.Scan(&amp;amp;n)

    for i := 0; i &amp;lt; n; i++ {
        var a, b int
        fmt.Scan(&amp;amp;a, &amp;amp;b)
        fmt.Println(a + b)
    }
    // 示例输出
    // 3
    // 7
    // 11
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. bufio.Scanner 快读模板（大数据量防超时必备）&lt;/h3&gt;
&lt;p&gt;数据量大时 fmt.Scan 容易超时，使用 bufio 加速读取，按空白字符拆分输入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;bufio&quot;
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;strconv&quot;
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    // 按空白字符分割（空格、换行都算作分隔符）
    scanner.Split(bufio.ScanWords)
    // 扩大缓冲区适配大数据
    scanner.Buffer(make([]byte, 1024*1024), 1024*1024)

    // 读取 int 的辅助函数
    readInt := func() int {
        scanner.Scan()
        num, _ := strconv.Atoi(scanner.Text())
        return num
    }

    n := readInt()
    for i := 0; i &amp;lt; n; i++ {
        a := readInt()
        b := readInt()
        fmt.Println(a + b)
    }
    // 示例输出
    // 3
    // 7
    // 11
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;二、排序技巧&lt;/h2&gt;
&lt;h3&gt;1. 基础切片排序&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;sort.Ints：int 切片升序快捷排序&lt;/li&gt;
&lt;li&gt;sort.Slice + 闭包：自定义排序规则&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;
    &quot;sort&quot;
    &quot;math&quot;
)

func main() {
    nums := []int{3, 1, 4, 1, 5, 9}

    // 升序（快捷写法）
    sort.Ints(nums)
    fmt.Println(nums) // [1 1 3 4 5 9]

    // 降序（自定义 less 函数）
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] &amp;gt; nums[j]
    })
    fmt.Println(nums) // [9 5 4 3 1 1]

    // 按绝对值降序排序
    nums1 := []int{1, -3, 5, -9, 4, -1}
    sort.Slice(nums1, func(i, j int) bool {
        absI := math.Abs(float64(nums1[i]))
        absJ := math.Abs(float64(nums1[j]))
        return absI &amp;gt; absJ
    })
    fmt.Println(nums1) // [-9 5 4 -3 1 -1]

    // 按绝对值升序排序
    nums2 := []int{1, -3, 5, -9, 4, -1}
    sort.Slice(nums2, func(i, j int) bool {
        absI := math.Abs(float64(nums2[i]))
        absJ := math.Abs(float64(nums2[j]))
        return absI &amp;lt; absJ
    })
    fmt.Println(nums2) // [1 -1 -3 4 5 -9]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;less 函数规则：返回 true 表示 i 元素排在 j 元素前面&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;2. 结构体切片排序&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;
    &quot;sort&quot;
)

type Student struct {
    Name  string
    Score int
}

func main() {
    students := []Student{
        {&quot;Alice&quot;, 85},
        {&quot;Bob&quot;, 92},
        {&quot;Charlie&quot;, 78},
    }

    // 按分数降序排列
    sort.Slice(students, func(i, j int) bool {
        return students[i].Score &amp;gt; students[j].Score
    })

    for _, s := range students {
        fmt.Printf(&quot;%s: %d\n&quot;, s.Name, s.Score)
    }
    // 输出
    // Bob: 92
    // Alice: 85
    // Charlie: 78
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 多级排序&lt;/h3&gt;
&lt;p&gt;示例规则：先按分数降序，分数相同则按名字字典序升序&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;
    &quot;sort&quot;
)

type Student struct {
    Name  string
    Score int
}

func main() {
    students := []Student{
        {&quot;Charlie&quot;, 85},
        {&quot;Alice&quot;, 92},
        {&quot;Bob&quot;, 85},
        {&quot;Alice&quot;, 85},
    }

    sort.Slice(students, func(i, j int) bool {
        // 第一关键字：分数降序
        if students[i].Score != students[j].Score {
            return students[i].Score &amp;gt; students[j].Score
        }
        // 第二关键字：名字字典序升序
        return students[i].Name &amp;lt; students[j].Name
    })

    for _, s := range students {
        fmt.Printf(&quot;%s: %d\n&quot;, s.Name, s.Score)
    }
    // 输出
    // Alice: 92
    // Alice: 85
    // Bob: 85
    // Charlie: 85
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;三、常用数学操作 &amp;amp; 溢出防范&lt;/h2&gt;
&lt;h3&gt;1. math 包常用函数&lt;/h3&gt;
&lt;p&gt;⚠️ math 包函数基本只接收 float64 类型，int 需要手动类型转换&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;
    &quot;math&quot;
)

func main() {
    // 绝对值
    fmt.Println(math.Abs(-5.0))
    x := -5
    fmt.Println(int(math.Abs(float64(x)))) // int 类型取绝对值

    // 开方
    fmt.Println(math.Sqrt(9))

    // 幂运算
    fmt.Println(math.Pow(2, 3))

    // 向下取整、向上取整
    fmt.Println(int(math.Floor(3.7))) // 3
    fmt.Println(int(math.Ceil(3.2)))  // 4
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 整数边界常量&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;
    &quot;math&quot;
)

func main() {
    // int32 边界
    fmt.Println(math.MaxInt32) // 2147483647
    fmt.Println(math.MinInt32) // -2147483648

    // int64 边界
    fmt.Println(math.MaxInt64) // 9223372036854775807

    // int32 溢出演示
    var n int32 = math.MaxInt32
    n = n + 1
    fmt.Println(n) // -2147483648，发生溢出

    // 防溢出计算：先转为 int64 再运算
    var a, b int32 = 100000, 100000
    result := int64(a) * int64(b)
    fmt.Println(result) // 10000000000

    // 无穷大初始化技巧
    minVal := math.MaxInt32
    nums := []int{5, 2, 8, 1, 9}
    for _, v := range nums {
        if v &amp;lt; minVal {
            minVal = v
        }
    }
    fmt.Println(minVal) // 1
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;刷题建议：优先使用原生 int（64位系统等价 int64）降低溢出风险；大数运算显式用 int64&lt;/li&gt;
&lt;li&gt;Go1.21+ 可使用内置 min/max 函数，不要混用 math.Max/math.Min&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;四、优先队列模板（container/heap）&lt;/h2&gt;
&lt;p&gt;Go 标准库无现成优先队列，需实现 heap.Interface 接口&lt;/p&gt;
&lt;h3&gt;1. 小顶堆模板&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;container/heap&quot;
    &quot;fmt&quot;
)

// IntHeap 实现 heap.Interface
type IntHeap []int

func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] &amp;lt; h[j] } // 小顶堆核心规则
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }

func (h *IntHeap) Push(x interface{}) {
    *h = append(*h, x.(int))
}

func (h *IntHeap) Pop() interface{} {
    old := *h
    n := len(old)
    x := old[n-1]
    *h = old[:n-1]
    return x
}

func main() {
    h := &amp;amp;IntHeap{}
    heap.Init(h)

    // 入堆
    heap.Push(h, 3)
    heap.Push(h, 1)
    heap.Push(h, 4)
    heap.Push(h, 1)
    heap.Push(h, 5)

    // 查看堆顶元素（最小值）
    fmt.Println((*h)[0]) // 1
    // 堆长度
    fmt.Println(h.Len()) // 5

    // 依次弹出元素
    for h.Len() &amp;gt; 0 {
        fmt.Printf(&quot;%d &quot;, heap.Pop(h))
    }
    // 输出：1 1 3 4 5
    fmt.Println()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 大顶堆修改方法&lt;/h3&gt;
&lt;p&gt;仅修改 Less 函数比较方向即可：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func (h IntHeap) Less(i, j int) bool {
    return h[i] &amp;gt; h[j] // 大顶堆核心规则
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;优先队列使用要点&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;入堆：&lt;code&gt;heap.Push(h, val)&lt;/code&gt;，不要直接调用 h.Push&lt;/li&gt;
&lt;li&gt;出堆：&lt;code&gt;heap.Pop(h)&lt;/code&gt;，不要直接调用 h.Pop&lt;/li&gt;
&lt;li&gt;查看堆顶：&lt;code&gt;(*h)[0]&lt;/code&gt;，直接访问底层切片首位&lt;/li&gt;
&lt;li&gt;判空：&lt;code&gt;h.Len() &amp;gt; 0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;五、整体刷题小结&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;I/O：小规模输入可用 fmt.Scan；大数据量直接用 bufio 快读避免超时&lt;/li&gt;
&lt;li&gt;排序：优先 sort.Slice + 闭包自定义 less 函数，支持单条件/结构体/多级排序&lt;/li&gt;
&lt;li&gt;数值计算：注意类型转换和溢出问题，大数运算用 int64&lt;/li&gt;
&lt;li&gt;优先队列：套用 heap 模板，通过修改 Less 函数实现大小顶堆&lt;/li&gt;
&lt;li&gt;基础工具：善用 math 包函数，注意 float64 类型限制；可用 MaxInt32 表示无穷大&lt;/li&gt;
&lt;/ol&gt;
</content:encoded></item><item><title>ACM模式</title><link>https://fuwari.vercel.app/posts/acm%E6%A8%A1%E5%BC%8F/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/acm%E6%A8%A1%E5%BC%8F/</guid><pubDate>Wed, 15 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;ACM模式：读取至EOF模板笔记&lt;/h1&gt;
&lt;h2&gt;核心关键点&lt;/h2&gt;
&lt;p&gt;ACM OJ 题目&lt;strong&gt;测试用例组数不固定，需要持续读取输入直到 EOF（输入结束标记），不能固定循环次数读取&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;基础模板：fmt.Scan + EOF 判断&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;fmt&quot;
    &quot;io&quot;
)

func add(a, b int) int {
    return a + b
}

func main() {
    var a, b int
    // 循环读取，直到读到EOF结束
    for {
        _, err := fmt.Scan(&amp;amp;a, &amp;amp;b)
        if err != nil {
            // 判断是否为正常输入结束
            if err == io.EOF {
                break
            }
            // 非EOF错误，抛出异常
            panic(err)
        }
        result := add(a, b)
        fmt.Println(result)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;重要注意事项&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;题目结构参考
&lt;ul&gt;
&lt;li&gt;题目示例：查看输入格式、每行数据结构、字段数量和类型&lt;/li&gt;
&lt;li&gt;自测用例：多行连续输入，无固定行数，模拟真实OJ评测输入&lt;/li&gt;
&lt;li&gt;完整流程：导包 → 循环读取并解析输入 → 算法计算 → 逐行输出结果&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;错误判断逻辑
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fmt.Scan&lt;/code&gt; 返回 &lt;code&gt;err&lt;/code&gt;：读到末尾时错误为 &lt;code&gt;io.EOF&lt;/code&gt; → 正常退出循环&lt;/li&gt;
&lt;li&gt;其他错误（格式错误等）用 &lt;code&gt;panic&lt;/code&gt; 抛出，方便调试&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;大数据版本：bufio快读 + EOF循环&lt;pre&gt;&lt;code&gt;package main

import (
    &quot;bufio&quot;
    &quot;fmt&quot;
    &quot;os&quot;
    &quot;strconv&quot;
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Split(bufio.ScanWords)
    scanner.Buffer(make([]byte, 1024*1024), 1024*1024)

    readInt := func() int {
        scanner.Scan()
        num, _ := strconv.Atoi(scanner.Text())
        return num
    }

    for scanner.Scan() {
        a := readInt()
        b := readInt()
        fmt.Println(a + b)
    }
    // 检查扫描器是否存在非EOF错误
    if err := scanner.Err(); err != nil {
        panic(err)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;易错坑
&lt;ul&gt;
&lt;li&gt;❌ 不要直接写固定n次循环（&lt;code&gt;for i:=0;i&amp;lt;n;i++&lt;/code&gt;），无法适配未知组数用例&lt;/li&gt;
&lt;li&gt;✅ 用无限循环 + EOF检测，保证读取全部输入&lt;/li&gt;
&lt;li&gt;✅ 保证输出格式和题目要求完全一致（换行、空格格式）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;EOF含义&lt;/h3&gt;
&lt;p&gt;EOF = End of File，代表输入流结束，在线评测系统会一次性输入全部测试数据并以EOF结尾；Windows控制台可按 &lt;code&gt;Ctrl+Z&lt;/code&gt;，Mac/Linux控制台可按 &lt;code&gt;Ctrl+D&lt;/code&gt; 手动触发EOF用于本地自测。&lt;/p&gt;
</content:encoded></item><item><title>260714GO包与导入</title><link>https://fuwari.vercel.app/posts/260714go%E5%8C%85%E4%B8%8E%E5%AF%BC%E5%85%A5/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/260714go%E5%8C%85%E4%B8%8E%E5%AF%BC%E5%85%A5/</guid><description>GO语言中的包与导入</description><pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;GO包与导入&lt;/h1&gt;
&lt;h2&gt;一、Go 的包（package）&lt;/h2&gt;
&lt;p&gt;Go 使用包（package）来组织和管理代码&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 &lt;code&gt;.go&lt;/code&gt; 文件&lt;strong&gt;第一行必须声明所属包&lt;/strong&gt;：&lt;code&gt;package 包名&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package main&lt;/code&gt; 是特殊包：
&lt;ul&gt;
&lt;li&gt;标识该包为&lt;strong&gt;可执行程序（编译后生成可运行文件）&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;程序入口：&lt;code&gt;main&lt;/code&gt; 包中的 &lt;code&gt;main()&lt;/code&gt; 函数，程序启动时自动执行 &lt;code&gt;main()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;非 main 包：是库包（被其他包引用，不能直接独立运行）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;同一个目录下所有 &lt;code&gt;.go&lt;/code&gt; 文件 &lt;strong&gt;必须声明为同一个包&lt;/strong&gt;；包名通常和目录名保持一致&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;二、import 导入&lt;/h2&gt;
&lt;p&gt;通过 &lt;code&gt;import&lt;/code&gt; 引入外部包，调用格式：&lt;code&gt;包名.函数名/类型名&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;1. 基础写法&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import &quot;fmt&quot;
import &quot;sort&quot;
import &quot;strings&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 分组导入写法（推荐）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import (
    &quot;fmt&quot;
    &quot;sort&quot;
    &quot;strings&quot;
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 导入规则&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Go 强制规则：&lt;strong&gt;导入但未使用的包会直接编译报错，不是警告&lt;/strong&gt;（Go 设计原则：避免冗余死代码）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;下划线匿名导入：仅执行包初始化、调用包内 &lt;code&gt;init()&lt;/code&gt; 函数，不直接调用包内方法&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import _ &quot;net/http/pprof&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;适用场景：数据库驱动注册、埋点/监控组件注册等，无需手动调用包内函数，只需完成初始化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 导入别名写法（补充）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import (
    s &quot;sort&quot;    // 自定义短别名 s 代替原包名 sort
    &quot;fmt&quot;
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;调用时：&lt;code&gt;s.Slice(...)&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;三、可见性规则（大小写控制导出/私有）&lt;/h2&gt;
&lt;p&gt;Go 没有 &lt;code&gt;public&lt;/code&gt; / &lt;code&gt;private&lt;/code&gt; 关键字，通过&lt;strong&gt;标识符首字母大小写控制跨包可见性&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;✅ &lt;strong&gt;首字母大写 = 导出（public）&lt;/strong&gt;：可被外部其他包访问&lt;pre&gt;&lt;code&gt;// 可跨包调用
func Factorial(n int) int { ... }
var MaxSize = 100
type Student struct {
    Name string // 大写字段：外部包可访问
    age  int    // 小写字段：仅本包可用
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;首字母小写 = 包内私有（private）&lt;/strong&gt;：仅当前包内部可用，外部包无法访问&lt;pre&gt;&lt;code&gt;// 仅本包内部调用
func helper() { ... }
var count = 0
type config struct { ... }
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;适用范围：函数、变量、常量、自定义类型、结构体字段等所有标识符&lt;/li&gt;
&lt;li&gt;例：标准库 &lt;code&gt;fmt.Println&lt;/code&gt;、&lt;code&gt;sort.Ints&lt;/code&gt;、&lt;code&gt;strings.ToUpper&lt;/code&gt; 均为大写导出，可供外部调用&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;四、init() 初始化函数&lt;/h2&gt;
&lt;h3&gt;特性&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;格式：&lt;code&gt;func init() {}&lt;/code&gt;，无参数、无返回值，&lt;strong&gt;不能手动调用&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;执行时机：包被导入时自动执行，执行顺序：
&lt;blockquote&gt;
&lt;p&gt;被依赖导入包的 init() → 当前包的 init() → main()&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;用途：初始化包级全局变量、注册组件、加载配置、预处理等
&lt;ul&gt;
&lt;li&gt;刷题场景极少用到；工程开发（数据库驱动、中间件）很常用&lt;/li&gt;
&lt;li&gt;同一个包内可写多个 &lt;code&gt;init()&lt;/code&gt; 函数，会按文件加载顺序依次自动执行&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;示例代码&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

// 包级别全局变量
var config string

// init 自动执行，在 main 之前运行
func init() {
    config = &quot;production&quot;
    fmt.Println(&quot;init() 执行了，config =&quot;, config)
}

func main() {
    fmt.Println(&quot;main() 执行了&quot;)
    fmt.Println(&quot;当前配置:&quot;, config)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;五、多文件组织&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;同一目录、同一个 &lt;code&gt;package&lt;/code&gt; 的多个 &lt;code&gt;.go&lt;/code&gt; 文件：&lt;strong&gt;可直接互相调用，无需额外 import&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;可以拆分代码：如 &lt;code&gt;utils.go&lt;/code&gt;（工具函数）、&lt;code&gt;main.go&lt;/code&gt;（主逻辑），互相自由调用变量/函数&lt;/li&gt;
&lt;li&gt;核心前提：所有文件开头包声明保持一致（如全部写 &lt;code&gt;package main&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;六、刷题常用标准库包一览&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fmt&lt;/code&gt;：格式化输入输出（Printf / Println / Scan）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sort&lt;/code&gt;：排序相关函数（sort.Slice、sort.Ints 等）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strings&lt;/code&gt;：字符串处理（查找、分割、大小写转换、匹配）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strconv&lt;/code&gt;：字符串与数值类型互相转换&lt;/li&gt;
&lt;li&gt;&lt;code&gt;math&lt;/code&gt;：数学运算（max/min、开方、取整、常数 Pi）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bufio&lt;/code&gt;：高效读取输入（读取整行、大数据输入）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;container/list&lt;/code&gt;：双向链表&lt;/li&gt;
&lt;li&gt;&lt;code&gt;time&lt;/code&gt;：时间处理&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bytes&lt;/code&gt;：字节数组处理&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>260714GO基础语法</title><link>https://fuwari.vercel.app/posts/260714go%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/260714go%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95/</guid><description>GO基础语法</description><pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;GO语言基础语法&lt;/h1&gt;
&lt;h2&gt;一、标准输出&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fmt.Println&lt;/code&gt;：打印后自动换行，多个参数之间用空格分隔&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fmt.Print&lt;/code&gt;：打印后不换行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fmt.Printf&lt;/code&gt;：格式化输出，和 C 语言的 &lt;code&gt;printf&lt;/code&gt; 类似，需手动加 &lt;code&gt;\n&lt;/code&gt; 换行&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;常用格式化占位符&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;%d&lt;/code&gt;：整数&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%s&lt;/code&gt;：字符串&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%f&lt;/code&gt;：浮点数
&lt;ul&gt;
&lt;li&gt;示例：&lt;code&gt;fmt.Printf(&quot;pi = %.2f\n&quot;, pi)&lt;/code&gt; 保留2位小数&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%c&lt;/code&gt;：打印字符&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%v&lt;/code&gt;：万能占位符，适配任意类型&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;fmt.Println(10, 20, &quot;hello&quot;)   // 自动换行，参数间空格分隔
fmt.Print(10, 20, &quot;hello&quot;)    // 不换行，参数间空格分隔
fmt.Printf(&quot;a = %d, b = %d\n&quot;, 10, 20) // 格式化模板输出
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;二、读取输入&lt;/h2&gt;
&lt;h3&gt;1. fmt.Scan&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;以空格/换行作为分隔符读取输入&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;变量前必须加 &lt;code&gt;&amp;amp;&lt;/code&gt; 传地址&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;var name string
var age int
fmt.Scan(&amp;amp;name, &amp;amp;age)
fmt.Println(&quot;姓名：&quot;, name)
fmt.Println(&quot;年龄：&quot;, age)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;返回值：&lt;code&gt;(n int, err error)&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;n&lt;/code&gt;：成功读取的变量个数&lt;/li&gt;
&lt;li&gt;&lt;code&gt;err&lt;/code&gt;：读取错误（正常为 &lt;code&gt;nil&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;_&lt;/code&gt;：空白标识符，用于丢弃不需要的返回值&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;循环读取直到 EOF&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

func main() {
    var a, b int
    for {
        n, err := fmt.Scan(&amp;amp;a, &amp;amp;b)
        if n != 2 || err != nil {
            break
        }
        fmt.Println(a + b)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 读取整行（含空格）bufio.Scanner&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main
import (
    &quot;bufio&quot;
    &quot;fmt&quot;
    &quot;os&quot;
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan()    // 读取一整行
    line := scanner.Text()
    fmt.Println(line)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;三、&amp;amp; 和 * 运算符&lt;/h2&gt;
&lt;h3&gt;1. &amp;amp; 取地址运算符&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;变量&lt;/code&gt;：获取变量内存地址，生成指针
&lt;ul&gt;
&lt;li&gt;例：&lt;code&gt;var a int; p := &amp;amp;a&lt;/code&gt;，&lt;code&gt;p&lt;/code&gt; 类型为 &lt;code&gt;*int&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;作用：传递原始变量地址，允许函数修改原变量（不是副本）&lt;/li&gt;
&lt;li&gt;关键：&lt;code&gt;fmt.Scan&lt;/code&gt; 需要指针参数才能正确写入值，不能直接传变量本身&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. * 解引用运算符&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;*指针变量&lt;/code&gt;：访问/修改指针指向的原始变量&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var a int
p := &amp;amp;a
*p = 100 // 通过指针修改原变量 a
fmt.Println(a) // 输出 100
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;类型声明写法：&lt;code&gt;var p *int&lt;/code&gt; 表示 &lt;code&gt;int&lt;/code&gt; 指针类型（和表达式解引用语法不同）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;x&lt;/code&gt;：取 x 的地址 → 生成指针&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*p&lt;/code&gt;：顺着指针地址访问原值&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;h2&gt;四、变量与数据类型&lt;/h2&gt;
&lt;h3&gt;1. 基础类型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;bool&lt;/code&gt;：布尔（&lt;code&gt;true&lt;/code&gt; / &lt;code&gt;false&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;string&lt;/code&gt;：UTF-8 字符串&lt;/li&gt;
&lt;li&gt;整数：&lt;code&gt;int&lt;/code&gt; / &lt;code&gt;int8&lt;/code&gt; / &lt;code&gt;int16&lt;/code&gt; / &lt;code&gt;int32&lt;/code&gt; / &lt;code&gt;int64&lt;/code&gt; / &lt;code&gt;uint&lt;/code&gt; / &lt;code&gt;uint8(byte)&lt;/code&gt; / &lt;code&gt;uint16&lt;/code&gt; / &lt;code&gt;uint32&lt;/code&gt; / &lt;code&gt;uint64&lt;/code&gt; / &lt;code&gt;uintptr&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rune&lt;/code&gt;：&lt;code&gt;int32&lt;/code&gt; 别名，用于 Unicode 字符&lt;/li&gt;
&lt;li&gt;浮点数：&lt;code&gt;float32&lt;/code&gt; / &lt;code&gt;float64&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;复数：&lt;code&gt;complex64&lt;/code&gt; / &lt;code&gt;complex128&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 复合类型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;数组 &lt;code&gt;[N]T&lt;/code&gt;：固定长度，值类型&lt;/li&gt;
&lt;li&gt;切片 &lt;code&gt;[]T&lt;/code&gt;：动态数组，引用类型（需 make）&lt;/li&gt;
&lt;li&gt;Map &lt;code&gt;map[KeyType]ValueType&lt;/code&gt;：哈希映射，引用类型（需 make）&lt;/li&gt;
&lt;li&gt;Struct：结构体，自定义聚合类型&lt;/li&gt;
&lt;li&gt;Channel &lt;code&gt;chan T&lt;/code&gt;：通道，goroutine 通信（需 make）&lt;/li&gt;
&lt;li&gt;Pointer &lt;code&gt;*T&lt;/code&gt;：指针类型&lt;/li&gt;
&lt;li&gt;Function：函数类型&lt;/li&gt;
&lt;li&gt;Interface：接口类型&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 变量规则&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Go 强制要求：声明变量必须使用，否则编译报错&lt;/li&gt;
&lt;li&gt;临时忽略值：用空白标识符 &lt;code&gt;_&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 常量 const&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;const MaxSize = 100
const Pi = 3.14159
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;常量定义后不可修改&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. 显式类型转换&lt;/h3&gt;
&lt;p&gt;Go &lt;strong&gt;无隐式自动类型转换，必须显式转换&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;a := 42
b := float64(a)
fmt.Println(b)

c := 3.99
d := int(c) // 截断小数，不是四舍五入 → 结果 3
fmt.Println(d)

// 整数除法坑
x, y := 1, 2
fmt.Println(x / y)                  // int除法：0
fmt.Println(float64(x) / float64(y))// 浮点数除法：0.5

var e int = 100
var f int64 = int64(e)
fmt.Println(f)

// 数值转字符串
num := 42
s := fmt.Sprintf(&quot;%d&quot;, num)
fmt.Printf(&quot;%s (string)\n&quot;, s)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;五、运算符&lt;/h2&gt;
&lt;h3&gt;1. 算术运算符&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;a, b := 17, 5
fmt.Println(a + b) // 加法
fmt.Println(a - b) // 减法
fmt.Println(a * b) // 乘法
fmt.Println(a / b) // 整数除法，截断小数
fmt.Println(a % b) // 取余

// 自增/自减：只能独立语句，不能嵌入表达式
c := 10
c++
fmt.Println(c)
c--
fmt.Println(c)

// 复合赋值
c += 5
c *= 2
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 比较 &amp;amp; 逻辑运算符&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;a, b := 10, 20
// 比较
fmt.Println(a == b)
fmt.Println(a != b)
fmt.Println(a &amp;lt; b)

// 逻辑
fmt.Println(a &amp;gt; 5 &amp;amp;&amp;amp; b &amp;gt; 15)  // &amp;amp;&amp;amp; 并且
fmt.Println(a &amp;gt; 100 || b &amp;gt; 15) // || 或者
fmt.Println(!(a &amp;gt; 5))         // ! 取反
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;❗ Go &lt;strong&gt;没有三元运算符 &lt;code&gt;?:&lt;/code&gt;&lt;/strong&gt;，只能用 if-else&lt;pre&gt;&lt;code&gt;var max int
if a &amp;gt; b {
    max = a
} else {
    max = b
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 位运算&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;a := 10 // 1010
b := 12 // 1100

fmt.Println(a &amp;amp; b)  // 按位与
fmt.Println(a | b)  // 按位或
fmt.Println(a ^ b)  // 按位异或
fmt.Println(a &amp;lt;&amp;lt; 1) // 左移（×2）
fmt.Println(a &amp;gt;&amp;gt; 1) // 右移（÷2）

// 判断奇偶
n := 7
if n&amp;amp;1 == 1 {
    fmt.Printf(&quot;%d 是奇数\n&quot;, n)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;六、控制流&lt;/h2&gt;
&lt;h3&gt;1. if / else 条件判断&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;条件&lt;strong&gt;不用括号 &lt;code&gt;()&lt;/code&gt;&lt;/strong&gt;，左大括号 &lt;code&gt;{&lt;/code&gt; 必须和 if 同行&lt;/li&gt;
&lt;li&gt;支持前置局部变量声明&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;score := 85
if score &amp;gt;= 90 {
    fmt.Println(&quot;优秀&quot;)
} else if score &amp;gt;= 60 {
    fmt.Println(&quot;及格&quot;)
} else {
    fmt.Println(&quot;不及格&quot;)
}

// 前置变量写法
if num := 10; num%2 == 0 {
    fmt.Println(&quot;偶数&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. for 循环（Go 唯一循环语句）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// 写法1：经典for
for i := 0; i &amp;lt; 5; i++ {
    fmt.Print(i, &quot; &quot;)
}
fmt.Println()

// 写法2：类while
sum := 0
i := 1
for i &amp;lt;= 100 {
    sum += i
    i++
}
fmt.Println(sum)

// 写法3：无限循环
count := 0
for {
    count++
    if count &amp;gt;= 3 {
        break
    }
}
fmt.Println(count)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. range 遍历&lt;/h3&gt;
&lt;p&gt;返回：索引 i, 元素值 v&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;nums := [5]int{10, 20, 30, 40, 50}

// 完整接收索引和值
for i, v := range nums {
    fmt.Printf(&quot;索引 %d：值 %d\n&quot;, i, v)
}

// 只取值，用 _ 忽略索引
for _, v := range nums {
    fmt.Print(v, &quot; &quot;)
}
fmt.Println()

// 只取索引
for i := range nums {
    fmt.Print(i, &quot; &quot;)
}
fmt.Println()
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. break / continue&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;break&lt;/code&gt;：跳出整个循环&lt;/li&gt;
&lt;li&gt;&lt;code&gt;continue&lt;/code&gt;：跳过本轮循环，直接进入下一轮&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;// break 示例
for i := 1; i &amp;lt;= 100; i++ {
    if i%7 == 0 {
        fmt.Println(&quot;第一个能被7整除的数：&quot;, i)
        break
    }
}

// continue 示例
for i := 1; i &amp;lt;= 10; i++ {
    if i%2 == 0 {
        continue
    }
    fmt.Print(i, &quot; &quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. switch&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;默认自动 break，不会穿透 case&lt;/li&gt;
&lt;li&gt;可多值匹配，也可无表达式作为 if-else 链使用&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;var day int
fmt.Scan(&amp;amp;day)
switch day {
case 1:
    fmt.Println(&quot;星期一&quot;)
case 2:
    fmt.Println(&quot;星期二&quot;)
case 3:
    fmt.Println(&quot;星期三&quot;)
case 6, 7:
    fmt.Println(&quot;周末&quot;)
default:
    fmt.Println(&quot;其他工作日&quot;)
}

// 无表达式 switch
score := 85
switch {
case score &amp;gt;= 90:
    fmt.Println(&quot;优秀&quot;)
case score &amp;gt;= 60:
    fmt.Println(&quot;及格&quot;)
default:
    fmt.Println(&quot;不及格&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>260714GO函数和指针</title><link>https://fuwari.vercel.app/posts/260714go%E5%87%BD%E6%95%B0%E5%92%8C%E6%8C%87%E9%92%88/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/260714go%E5%87%BD%E6%95%B0%E5%92%8C%E6%8C%87%E9%92%88/</guid><description>GO语言中的函数和指针</description><pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;GO 函数与指针&lt;/h1&gt;
&lt;h2&gt;一、函数基础&lt;/h2&gt;
&lt;p&gt;函数是可重复调用的代码块，用于拆分代码、提高复用性、增强可读性&lt;/p&gt;
&lt;h3&gt;1. 函数定义与调用&lt;/h3&gt;
&lt;p&gt;语法：&lt;code&gt;func 函数名(参数列表) 返回类型 { 函数体 }&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

// 有返回值函数：计算两数之和
func add(a, b int) int {
    return a + b
}

// 无返回值函数
func greet(name string) {
    fmt.Println(&quot;你好，&quot; + name + &quot;！&quot;)
}

func main() {
    fmt.Println(add(3, 5)) // 调用函数
    greet(&quot;小明&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;func&lt;/code&gt;：函数关键字&lt;/li&gt;
&lt;li&gt;参数写法：可简写同类型参数 &lt;code&gt;(a, b int)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;无返回值：不写返回类型即可&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 多返回值&lt;/h3&gt;
&lt;p&gt;Go 支持函数返回多个值，常用于同时返回结果和错误信息&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 返回商、余数两个 int 值
func divide(a, b int) (int, int) {
    return a / b, a % b
}

func main() {
    q, r := divide(10, 3)
    fmt.Printf(&quot;商 = %d, 余数 = %d\n&quot;, q, r)

    // 空白标识符 _ 忽略不需要的返回值，避免编译报错
    _, remainder := divide(17, 5)
    fmt.Println(&quot;余数 =&quot;, remainder)

    quotient, _ := divide(20, 7)
    fmt.Println(&quot;商 =&quot;, quotient)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_&lt;/code&gt;：空白标识符，用于丢弃不需要的返回值，解决未使用变量编译报错问题&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 命名返回值&lt;/h3&gt;
&lt;p&gt;可直接为返回值命名，函数内可直接赋值，使用空 &lt;code&gt;return&lt;/code&gt; 自动返回&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func divide(a, b int) (quotient, remainder int) {
    quotient = a / b
    remainder = a % b
    return // 空 return，自动返回命名变量
}

func main() {
    q, r := divide(10, 3)
    fmt.Printf(&quot;商 = %d, 余数 = %d\n&quot;, q, r)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;二、指针&lt;/h2&gt;
&lt;h3&gt;1. 指针基础&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;指针变量：存储另一个变量的&lt;strong&gt;内存地址&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;两个核心运算符：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;：取地址运算符，获取变量内存地址&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*&lt;/code&gt;：解引用运算符，通过地址访问/修改原变量&lt;/li&gt;
&lt;li&gt;指针类型写法：&lt;code&gt;*int&lt;/code&gt;、&lt;code&gt;*string&lt;/code&gt; 等，表示指向对应类型的指针&lt;/li&gt;
&lt;li&gt;✅ Go 指针&lt;strong&gt;不支持指针算术运算（p++ 等）&lt;/strong&gt;，保证安全&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

func main() {
    a := 42
    var p *int = &amp;amp;a // p 是 *int 指针，保存 a 的内存地址
    fmt.Println(&quot;a 的地址：&quot;, p)
    fmt.Println(&quot;*p =&quot;, *p) // 解引用读取原值

    *p = 100 // 解引用修改原变量 a
    fmt.Println(&quot;a =&quot;, a) // a 变为 100

    // 简写方式
    b := 99
    p2 := &amp;amp;b
    fmt.Println(&quot;*p2 =&quot;, *p2)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 值传递 vs 指针传参&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Go 默认参数是 &lt;strong&gt;值传递&lt;/strong&gt;：传入变量副本，修改副本不会影响外部原变量&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;// 值传递：修改的只是副本，外部变量不变
func tryChange(x int) {
    x = 999
    fmt.Println(&quot;函数内 x =&quot;, x)
}

// 指针传参：直接修改外部原变量
func changeValue(p *int) {
    *p = 999
}

// 交换两个变量（指针版本）
func swap(a, b *int) {
    *a, *b = *b, *a
}

func main() {
    a := 10
    tryChange(a)
    fmt.Println(&quot;a =&quot;, a) // a 仍然是 10

    changeValue(&amp;amp;a)
    fmt.Println(&quot;a =&quot;, a) // a 变为 999

    x, y := 1, 2
    swap(&amp;amp;x, &amp;amp;y)
    fmt.Printf(&quot;x = %d, y = %d\n&quot;, x, y) // x=2 y=1
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. slice、map 参数传递特性&lt;/h3&gt;
&lt;p&gt;slice 和 map 底层结构自带指针，传递时不需要额外加 &lt;code&gt;*&lt;/code&gt;，函数内修改元素会直接影响外部原数据&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

// 修改切片元素，直接影响原切片
func doubleSlice(nums []int) {
    for i := range nums {
        nums[i] *= 2
    }
}

// 修改 map，直接影响原 map
func addEntry(m map[string]int, key string, value int) {
    m[key] = value
}

func main() {
    nums := []int{1, 2, 3, 4, 5}
    doubleSlice(nums)
    fmt.Println(nums) // [2 4 6 8 10]

    scores := map[string]int{&quot;Alice&quot;: 90}
    addEntry(scores, &quot;Bob&quot;, 85)
    fmt.Println(scores) // map[Alice:90 Bob:85]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;map 初始化方式&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;// 方式1：字面量初始化
scores := map[string]int{&quot;Alice&quot;: 90}

// 方式2：make 初始化（推荐动态使用）
scores := make(map[string]int)
scores[&quot;Alice&quot;] = 90
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;❗ nil map 不能直接赋值，必须先用 make / 字面量初始化&lt;/li&gt;
&lt;li&gt;map 取值检查：&lt;code&gt;val, ok := scores[&quot;Alice&quot;]&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;val：对应 value 值&lt;/li&gt;
&lt;li&gt;ok：bool 类型，表示 key 是否存在&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;三、错误处理（error）&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Go 没有 try/catch 异常机制，依靠&lt;strong&gt;多返回值 error 做错误处理&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;调用函数后主动检查 err 是否为 nil&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;常见多返回值函数&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;fmt.Scan&lt;/code&gt; → &lt;code&gt;(n int, err error)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strconv.Atoi&lt;/code&gt; → &lt;code&gt;(int, error)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;os.Open&lt;/code&gt; → &lt;code&gt;(*os.File, error)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;map 取值：&lt;code&gt;val, ok := m[&quot;key&quot;]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;range 遍历：&lt;code&gt;i, v := range arr&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;四、匿名函数 &amp;amp; 闭包&lt;/h2&gt;
&lt;h3&gt;1. 匿名函数&lt;/h3&gt;
&lt;p&gt;没有函数名的函数，可以赋值给变量、直接调用&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

func main() {
    // 匿名函数赋值给变量
    add := func(a, b int) int {
        return a + b
    }
    fmt.Println(add(3, 5)) // 8
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 闭包&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;闭包 = &lt;strong&gt;可以捕获外层变量的匿名函数&lt;/strong&gt;，会保留引用外部变量，而非复制副本&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

func main() {
    x := 10
    addX := func(n int) int {
        return n + x // 捕获外部变量 x
    }
    fmt.Println(addX(5)) // 15

    x = 100 // 修改外部变量，闭包可感知变化
    fmt.Println(addX(5)) // 105
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 闭包 + sort.Slice 自定义排序&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sort.Slice(slice, less func(i,j int) bool)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;参数1：目标切片&lt;/li&gt;
&lt;li&gt;参数2：less 闭包函数：i,j 为索引，返回 bool
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;true&lt;/code&gt;：i 元素排在 j 前面&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;package main
import (
    &quot;fmt&quot;
    &quot;sort&quot;
)

func main() {
    nums := []int{3, 1, 4, 1, 5, 9, 2, 6}
    // 升序排序
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] &amp;lt; nums[j]
    })
    fmt.Println(nums) // [1 1 2 3 4 5 6 9]

    // 按绝对值从大到小排序
    nums2 := []int{-3, 1, -4, 1, 5, -9, 2, -6}
    sort.Slice(nums2, func(i, j int) bool {
        a, b := nums2[i], nums2[j]
        if a &amp;lt; 0 { a = -a }
        if b &amp;lt; 0 { b = -b }
        return a &amp;gt; b
    })
    fmt.Println(nums2) // [-9 -6 5 -4 -3 2 1 1]
}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>260714GO常用数据结构</title><link>https://fuwari.vercel.app/posts/260714go%E5%B8%B8%E7%94%A8%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/260714go%E5%B8%B8%E7%94%A8%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/</guid><description>GO语言中的常用数据结构</description><pubDate>Tue, 14 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;GO 常用数据结构&lt;/h1&gt;
&lt;h2&gt;一、数组与切片&lt;/h2&gt;
&lt;h3&gt;1. 数组 Array&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;特点：&lt;strong&gt;长度固定、声明时必须指定大小，属于值类型，不能动态扩容&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;package main
import &quot;fmt&quot;

func main() {
    // 声明长度为5的int数组，默认零值全为0
    var arr [5]int
    fmt.Println(arr) // [0 0 0 0 0]

    // 下标赋值
    arr[0] = 10
    arr[1] = 20
    fmt.Println(arr) // [10 20 0 0 0]

    // 初始化数组
    nums := [5]int{1, 2, 3, 4, 5}
    fmt.Println(nums) // [1 2 3 4 5]

    // 获取数组长度
    fmt.Println(len(nums)) // 5
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;缺点：长度固定，灵活性差，实际开发很少直接使用，优先用切片 slice&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 切片 Slice&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;特点：动态可变数组，类型写法 &lt;code&gt;[]int&lt;/code&gt;（无固定长度数字），引用类型，底层依托数组&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;创建方式&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    // 方式1：字面量创建
    nums := []int{1, 2, 3, 4, 5}
    fmt.Println(nums) // [1 2 3 4 5]

    // 方式2：make 指定长度
    a := make([]int, 5)
    fmt.Println(a) // [0 0 0 0 0]

    // 方式3：make 指定长度 + 容量
    b := make([]int, 3, 10)
    fmt.Println(b) // [0 0 0]
    fmt.Printf(&quot;长度=%d, 容量=%d\n&quot;, len(b), cap(b)) // len=3, cap=10

    // 下标访问修改
    nums[0] = 100
    fmt.Println(nums[0]) // 100

    // range遍历
    for _, v := range nums {
        fmt.Print(v, &quot; &quot;)
    }
    fmt.Println()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;len()&lt;/code&gt;：当前实际元素数量&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cap()&lt;/code&gt;：底层数组总容量；超出容量时 Go 自动扩容，重新分配底层数组&lt;/li&gt;
&lt;li&gt;&lt;code&gt;...&lt;/code&gt;：切片展开语法，把切片拆成独立参数传给 append&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;切片增删 &amp;amp; 截取&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    nums := []int{1, 2, 3}

    // 末尾追加元素
    nums = append(nums, 4)
    nums = append(nums, 5, 6)
    fmt.Println(nums) // [1 2 3 4 5 6]

    // 切片截取 nums[start:end]：含start，不含end
    fmt.Println(nums[1:4]) // [2 3 4]
    fmt.Println(nums[:3])  // [1 2 3] 省略start：从头开始
    fmt.Println(nums[3:])  // [4 5 6] 省略end：到末尾

    // 删除索引 i 的元素
    i := 2
    nums = append(nums[:i], nums[i+1:]...)
    fmt.Println(nums) // [1 2 4 5 6]

    // 在索引 i 插入元素
    i = 1
    nums = append(nums[:i], append([]int{99}, nums[i:]...)...)
    fmt.Println(nums) // [1 99 2 4 5 6]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;二维切片&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    rows, cols := 3, 4
    // 创建外层切片
    grid := make([][]int, rows)
    // 逐行创建内层一维切片
    for i := 0; i &amp;lt; rows; i++ {
        grid[i] = make([]int, cols)
    }

    // 赋值
    grid[0][0] = 1
    grid[1][2] = 5
    grid[2][3] = 9

    fmt.Printf(&quot;%d 行 %d 列\n&quot;, len(grid), len(grid[0]))
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;内存结构&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;grid (外层切片)
 ├─ grid[0] → [0, 0, 0, 0]
 ├─ grid[1] → [0, 0, 0, 0]
 └─ grid[2] → [0, 0, 0, 0]
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;二、字符串 string&lt;/h2&gt;
&lt;h3&gt;基础特性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;字符串不可直接修改单个字符&lt;/strong&gt;（底层是只读字节数组）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;len(s)&lt;/code&gt;：获取字节长度；下标访问得到 &lt;code&gt;byte&lt;/code&gt; 字节&lt;/li&gt;
&lt;li&gt;&lt;code&gt;range&lt;/code&gt; 遍历可正确读取 Unicode 字符（rune）&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    s := &quot;Hello, Go!&quot;
    fmt.Println(len(s))         // 10 字节
    fmt.Println(s[0])           // 72 (H的ASCII码)
    fmt.Printf(&quot;%c\n&quot;, s[0])    // H
    fmt.Println(s[0:5])         // Hello 截取

    // 字符串拼接
    greeting := &quot;你好&quot; + &quot;，世界&quot;
    fmt.Println(greeting)

    // 字符串比较
    fmt.Println(&quot;hello&quot; == &quot;hello&quot;) // true

    // range遍历 Unicode
    for _, ch := range &quot;Hello&quot; {
        fmt.Printf(&quot;%c &quot;, ch)
    }
    fmt.Println()

    // s[0] = &apos;h&apos; // ❌ 编译报错：字符串不可变
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;[]byte 与 []rune 转换&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[]byte&lt;/code&gt;：按字节处理，适合纯 ASCII 英文/数字&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[]rune&lt;/code&gt;：按 Unicode 字符处理，适合中文、emoji 等多字节字符&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;s := &quot;abc中文&quot;
b := []byte(s)    // 转为字节数组
r := []rune(s)    // 转为 Unicode 字符数组
newS := string(b) // 转回字符串
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;strings 包常用函数&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main
import (
    &quot;fmt&quot;
    &quot;strings&quot;
)
func main() {
    s := &quot;Hello, World!&quot;
    fmt.Println(strings.Contains(s, &quot;World&quot;))    // 是否包含子串 true
    fmt.Println(strings.Index(s, &quot;World&quot;))       // 子串起始索引 7
    fmt.Println(strings.HasPrefix(s, &quot;Hello&quot;))   // 是否前缀 true
    fmt.Println(strings.HasSuffix(s, &quot;World!&quot;))  // 是否后缀 true

    csv := &quot;apple,banana,cherry&quot;
    parts := strings.Split(csv, &quot;,&quot;)             // 分割字符串
    fmt.Println(strings.Join(parts, &quot; - &quot;))      // 拼接切片
    fmt.Println(strings.Replace(&quot;aabbaabb&quot;, &quot;aa&quot;, &quot;cc&quot;, -1)) // 全部替换
    fmt.Println(strings.Repeat(&quot;Go&quot;, 3))         // 重复字符串 GoGoGo
    fmt.Println(strings.ToUpper(&quot;hello&quot;))         // 转大写
    fmt.Println(strings.ToLower(&quot;HELLO&quot;))         // 转小写
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;strconv 包：字符串和数字互转&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main
import (
    &quot;fmt&quot;
    &quot;strconv&quot;
)
func main() {
    // Atoi：字符串转int
    n, err := strconv.Atoi(&quot;123&quot;)
    if err == nil {
        fmt.Println(n) // 123
    }

    // Itoa：int转字符串
    s := strconv.Itoa(42)
    fmt.Println(s) // 42

    // ParseInt：指定进制转整数
    num, _ := strconv.ParseInt(&quot;ff&quot;, 16, 64)
    fmt.Println(num) // 255

    // FormatInt：整数转指定进制字符串
    binStr := strconv.FormatInt(255, 2)
    fmt.Println(binStr) // 11111111
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;刷题高频：&lt;code&gt;strconv.Atoi&lt;/code&gt; / &lt;code&gt;strconv.Itoa&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;三、结构体 struct&lt;/h2&gt;
&lt;h3&gt;定义和初始化&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Go 没有 class，用 struct 聚合多个字段，可用于节点、实体建模&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;type Student struct {
    Name  string
    Age   int
    Score float64
}

func main() {
    // 按字段名初始化（推荐）
    s1 := Student{Name: &quot;Alice&quot;, Age: 20, Score: 95.5}
    fmt.Println(s1)

    // 按顺序初始化（不推荐）
    s2 := Student{&quot;Bob&quot;, 21, 88.0}
    fmt.Println(s2)

    // 访问&amp;amp;修改字段
    fmt.Println(s1.Name)
    s1.Age = 21
    fmt.Println(s1.Age)

    // 零值结构体
    var s3 Student
    fmt.Println(s3)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;结构体指针&lt;/h3&gt;
&lt;p&gt;Go 自动解引用指针字段，无需手动写 &lt;code&gt;(*p).X&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Point struct {
    X int
    Y int
}

func moveRight(p *Point, distance int) {
    p.X += distance // 直接使用 p.X
}

func main() {
    p := &amp;amp;Point{X: 3, Y: 4}
    fmt.Println(p.X) // 3
    moveRight(p, 10)
    fmt.Println(*p) // {13 4}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;四、哈希表 map&lt;/h2&gt;
&lt;h3&gt;基础用法&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;键值对存储，查找/增删效率高；必须用 make/字面量初始化，nil map 不能直接赋值&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    // make 创建空 map
    m := make(map[string]int)
    m[&quot;apple&quot;] = 3
    m[&quot;banana&quot;] = 5
    m[&quot;cherry&quot;] = 2
    fmt.Println(m[&quot;apple&quot;]) // 3

    m[&quot;apple&quot;] = 10       // 修改值
    delete(m, &quot;cherry&quot;)   // 删除键
    fmt.Println(len(m))   // 长度 2

    // 字面量初始化
    scores := map[string]int{
        &quot;Alice&quot;: 90,
        &quot;Bob&quot;:   85,
        &quot;Carol&quot;: 92,
    }

    // 遍历map（无序）
    for k, v := range scores {
        fmt.Printf(&quot;%s: %d\n&quot;, k, v)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;判断 key 是否存在&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    m := map[string]int{&quot;apple&quot;: 3, &quot;banana&quot;: 5}
    val, ok := m[&quot;apple&quot;]
    fmt.Println(val, ok) // 3 true

    val, ok = m[&quot;grape&quot;]
    fmt.Println(val, ok) // 0 false

    if val, ok := m[&quot;banana&quot;]; ok {
        fmt.Printf(&quot;banana 存在，值为 %d\n&quot;, val)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;哈希集合（用 map[T]struct{} 模拟）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;struct{}&lt;/code&gt; 空结构体不占用内存，适合实现集合去重&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    set := make(map[int]struct{})
    set[1] = struct{}{}
    set[2] = struct{}{}
    set[3] = struct{}{}
    set[2] = struct{}{} // 重复添加无效

    fmt.Println(len(set)) // 3

    // 判断存在
    if _, ok := set[2]; ok {
        fmt.Println(&quot;2 存在&quot;)
    }

    delete(set, 2) // 删除元素
    for k := range set {
        fmt.Print(k, &quot; &quot;)
    }
    fmt.Println()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;五、栈（用切片模拟）&lt;/h2&gt;
&lt;p&gt;后进先出（LIFO）&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func main() {
    stack := []int{}
    // 入栈
    stack = append(stack, 1)
    stack = append(stack, 2)
    stack = append(stack, 3)
    fmt.Println(stack) // [1 2 3]

    // 栈顶元素
    top := stack[len(stack)-1]
    fmt.Println(&quot;栈顶:&quot;, top) // 3

    // 出栈
    stack = stack[:len(stack)-1]
    fmt.Println(stack) // [1 2]

    // 判空
    fmt.Println(len(stack) == 0)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;入栈：&lt;code&gt;stack = append(stack, x)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;栈顶：&lt;code&gt;stack[len(stack)-1]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;出栈：&lt;code&gt;stack = stack[:len(stack)-1]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;判空：&lt;code&gt;len(stack) == 0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;六、队列（FIFO 先进先出）&lt;/h2&gt;
&lt;h3&gt;container/list 双向链表实现&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;package main
import (
    &quot;container/list&quot;
    &quot;fmt&quot;
)
func main() {
    queue := list.New()
    // 入队
    queue.PushBack(10)
    queue.PushBack(20)
    queue.PushBack(30)
    fmt.Println(&quot;大小:&quot;, queue.Len()) // 3

    // 队头元素（类型断言）
    front := queue.Front().Value.(int)
    fmt.Println(&quot;队头:&quot;, front) // 10

    // 出队
    queue.Remove(queue.Front())
    fmt.Println(&quot;新队头:&quot;, queue.Front().Value.(int)) // 20

    // 遍历
    for e := queue.Front(); e != nil; e = e.Next() {
        fmt.Print(e.Value.(int), &quot; &quot;)
    }
    fmt.Println()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;入队：&lt;code&gt;queue.PushBack(x)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;队头：&lt;code&gt;queue.Front().Value.(类型断言)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;出队：&lt;code&gt;queue.Remove(queue.Front())&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;判空：&lt;code&gt;queue.Len() == 0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;七、make 初始化规则&lt;/h2&gt;
&lt;h3&gt;✅ make 仅用于 3 种引用类型&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;slice 切片&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;s := make([]int, 3, 10) // 长度3，容量10
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;分配底层数组内存，减少反复扩容开销&lt;/li&gt;
&lt;li&gt;var s []int → nil 切片，无底层数组&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;map 字典&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;m := make(map[string]int, 10)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;初始化哈希表，避免 nil map 直接赋值 panic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;chan 通道&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ch := make(chan int, 5)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;初始化缓冲区，用于 goroutine 通信&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;❌ 不能用 make 的类型&lt;/h3&gt;
&lt;p&gt;普通变量、定长数组 &lt;code&gt;[N]int&lt;/code&gt;、string、bool、int、struct 等，直接声明即可&lt;/p&gt;
&lt;h3&gt;❗ new 和 make 的区别&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new(T)&lt;/code&gt;：返回 *T 指针，只分配基础结构内存，&lt;strong&gt;不初始化底层数据结构&lt;/strong&gt;&lt;pre&gt;&lt;code&gt;s := new([]int) // 仅切片结构体，无底层数组，不能直接索引赋值
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;make(T, ...)&lt;/code&gt;：返回原始引用类型，初始化底层数组/哈希表/缓冲区&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>用于测试的文章</title><link>https://fuwari.vercel.app/posts/testpaper/testpaper/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/testpaper/testpaper/</guid><description>用于测试的文章</description><pubDate>Mon, 13 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;博客的标签分类有：&lt;/p&gt;
&lt;p&gt;测试文章图片放置&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./content1.png&quot; alt=&quot;架构图&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>算法框架</title><link>https://fuwari.vercel.app/posts/260713%E7%AE%97%E6%B3%95%E6%A1%86%E6%9E%B6/%E7%AE%97%E6%B3%95%E6%A1%86%E6%9E%B6/</link><guid isPermaLink="true">https://fuwari.vercel.app/posts/260713%E7%AE%97%E6%B3%95%E6%A1%86%E6%9E%B6/%E7%AE%97%E6%B3%95%E6%A1%86%E6%9E%B6/</guid><description>算法框架</description><pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;数据结构的存储方式&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;./%E7%AE%97%E6%B3%95%E6%A1%86%E6%9E%B61.PNG&quot; alt=&quot;算法框架图&quot; /&gt;&lt;/p&gt;
&lt;p&gt;数据结构的存储方式只有两种：&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/array-basic/&quot;&gt;数组（顺序存储）&lt;/a&gt; 和 &lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/linkedlist-basic/&quot;&gt;链表（链式存储）&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;数组和链表才是结构基础&lt;/p&gt;
&lt;p&gt;哈希表、栈、队列、堆、树、图等等各种数据结构  都是在链表或者数组上的特殊操作，API 不同而已。&lt;/p&gt;
&lt;p&gt;二者的优缺点如下：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/array-basic/&quot;&gt;数组&lt;/a&gt; 紧凑连续存储，可以随机访问，通过索引快速找到对应元素，而且相对节约存储空间。但正因为连续存储，内存空间必须一次性分配够，所以说数组如果要扩容，需要重新分配一块更大的空间，再把数据全部复制过去，时间复杂度 O(N)；而且你如果想在数组中间进行插入和删除，每次必须搬移后面的所有数据以保持连续，时间复杂度 O(N)。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/linkedlist-basic/&quot;&gt;链表&lt;/a&gt; 因为元素不连续，而是靠指针指向下一个元素的位置，所以不存在数组的扩容问题；如果知道某一元素的前驱和后驱，操作指针即可删除该元素或者插入新元素，时间复杂度 O(1) &lt;em&gt;O&lt;/em&gt; (1)。但是正因为存储空间不连续，你无法根据一个索引算出对应元素的地址，所以不能随机访问；而且由于每个元素必须存储指向前后元素位置的指针，会消耗相对更多的储存空间。&lt;/p&gt;
&lt;p&gt;比如说 &lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/queue-stack-basic/&quot;&gt;队列、栈&lt;/a&gt; 这两种数据结构既可以使用链表也可以使用数组实现。用数组实现，就要处理扩容缩容的问题；用链表实现，没有这个问题，但需要更多的内存空间存储节点指针。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/graph-basic/&quot;&gt;图结构&lt;/a&gt; 的两种存储方式，邻接表就是链表，邻接矩阵就是二维数组。邻接矩阵判断连通性迅速，并可以进行矩阵运算解决一些问题，但是如果图比较稀疏的话很耗费空间。邻接表比较节省空间，但是很多操作的效率上肯定比不过邻接矩阵。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/hashmap-basic/&quot;&gt;哈希表&lt;/a&gt; 就是通过散列函数把键映射到一个大数组里。而且对于解决散列冲突的方法，&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/hashtable-chaining/&quot;&gt;拉链法&lt;/a&gt; 需要链表特性，操作简单，但需要额外的空间存储指针；&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/linear-probing-key-point/&quot;&gt;线性探查法&lt;/a&gt; 需要数组特性，以便连续寻址，不需要指针的存储空间，但操作稍微复杂些。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/binary-tree-basic/&quot;&gt;树结构&lt;/a&gt;，用数组实现就是「堆」，因为「堆」是一个完全二叉树，用数组存储不需要节点指针，操作也比较简单，经典应用有 &lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/binary-heap-basic/&quot;&gt;二叉堆&lt;/a&gt;；用链表实现就是很常见的那种「树」，因为不一定是完全二叉树，所以不适合用数组存储。为此，在这种链表「树」结构之上，又衍生出各种巧妙的设计，比如 &lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/tree-map-basic/&quot;&gt;二叉搜索树&lt;/a&gt;、AVL 树、&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/rbtree-basic/&quot;&gt;红黑树&lt;/a&gt;、&lt;a href=&quot;https://labuladong.online/zh/algo/data-structure-basic/segment-tree-basic/&quot;&gt;区间树&lt;/a&gt;、B 树等等，以应对不同的问题。&lt;/p&gt;
&lt;h2&gt;数据结构的基本操作&lt;/h2&gt;
&lt;p&gt;对于任何数据结构，其基本操作无非遍历 + 访问，再具体一点就是：增删查改。&lt;/p&gt;
&lt;p&gt;各种数据结构的遍历 + 访问无非两种形式：线性的和非线性的。&lt;/p&gt;
&lt;p&gt;线性就是 for/while 迭代为代表，非线性就是递归为代表。再具体一步，无非以下几种框架：&lt;/p&gt;
</content:encoded></item></channel></rss>