<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Golang-Study on Jamaisvu&#39;s blog</title>
    <link>https://tech.jamaisvu.cn/series/golang-study/</link>
    <description>Recent content in Golang-Study on Jamaisvu&#39;s blog</description>
    <image>
      <title>Jamaisvu&#39;s blog</title>
      <url>https://raw.githubusercontent.com/grayfalcon666/OSS-FOR-PICGO/main/1756602474727.jpg</url>
      <link>https://raw.githubusercontent.com/grayfalcon666/OSS-FOR-PICGO/main/1756602474727.jpg</link>
    </image>
    <generator>Hugo -- 0.160.1</generator>
    <language>en</language>
    <lastBuildDate>Fri, 24 Apr 2026 23:06:58 +0800</lastBuildDate>
    <atom:link href="https://tech.jamaisvu.cn/series/golang-study/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Golang并发编程</title>
      <link>https://tech.jamaisvu.cn/posts/golang-concurrency/</link>
      <pubDate>Fri, 24 Apr 2026 23:06:58 +0800</pubDate>
      <guid>https://tech.jamaisvu.cn/posts/golang-concurrency/</guid>
      <description>&lt;h2 id=&#34;几个概念&#34;&gt;几个概念&lt;/h2&gt;
&lt;h3 id=&#34;并行和并发&#34;&gt;并行和并发&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;并行
多线程程序在多个核的cpu上运行，就是并行
&lt;img alt=&#34;image.png|325&#34; loading=&#34;lazy&#34; src=&#34;https://raw.githubusercontent.com/grayfalcon666/OSS-FOR-PICGO2/refs/heads/main//20260105145842507.png&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;并发
多线程程序在一个核的cpu上运行，就是并发
&lt;img alt=&#34;image.png|325&#34; loading=&#34;lazy&#34; src=&#34;https://raw.githubusercontent.com/grayfalcon666/OSS-FOR-PICGO2/refs/heads/main//20260105145819249.png&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;进程和线程&#34;&gt;进程和线程&lt;/h3&gt;
&lt;p&gt;A. 进程是程序在操作系统中的一次执行过程，系统进行资源分配和调度的一个独立单位。比如你运行一个 Go 程序 &lt;code&gt;go run main.go&lt;/code&gt;，操作系统就会创建一个进程。每个进程有自己独立的内存空间、文件描述符、环境变量等，不同进程之间的资源默认是隔离的。
B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。多个线程共享所属进程的所有资源（内存、文件句柄等）
C.一个进程可以创建和撤销多个线程;同一个进程中的多个线程之间可以并发执行。&lt;/p&gt;
&lt;h3 id=&#34;协程和线程&#34;&gt;协程和线程&lt;/h3&gt;
&lt;p&gt;协程：独立的栈空间，共享堆空间，调度由用户自己控制，本质上有点类似于用户级线程，这些用户级线程的调度也是自己实现的。
线程：一个线程上可以跑多个协程，协程是轻量级的线程。&lt;/p&gt;
&lt;h2 id=&#34;goroutine&#34;&gt;Goroutine&lt;/h2&gt;
&lt;h3 id=&#34;启动单个goroutine&#34;&gt;启动单个goroutine&lt;/h3&gt;
&lt;p&gt;goroutine的概念类似于线程，但 goroutine是由Go的运行时（runtime）调度和管理的。Go程序会智能地将 goroutine 中的任务合理地分配给每个CPU。Go语言之所以被称为现代化的编程语言，就是因为它在语言层面已经内置了调度和上下文切换的机制。&lt;/p&gt;
&lt;p&gt;启动goroutine的方式非常简单，只需要在调用的函数（普通函数和匿名函数）前面加上一个go关键字。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;hello&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello Goroutine!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;hello&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;main goroutine done!&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;7&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;sleep&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;time&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Second&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;8&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;执行上面的代码你会发现，这一次先打印main goroutine done!，然后紧接着打印Hello Goroutine!。&lt;/p&gt;
&lt;h3 id=&#34;启动多个goroutine&#34;&gt;启动多个goroutine&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sync&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;WaitGroup&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;hello&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Done&lt;/span&gt;() &lt;span style=&#34;color:#75715e&#34;&gt;// goroutine结束就登记-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;fmt&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Println&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Hello Goroutine!&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7&lt;/span&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt; &amp;lt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;; &lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Add&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#75715e&#34;&gt;// 启动一个goroutine就登记+1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11&lt;/span&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;hello&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;i&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12&lt;/span&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13&lt;/span&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;wg&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;Wait&lt;/span&gt;() &lt;span style=&#34;color:#75715e&#34;&gt;// 等待所有登记的goroutine都结束&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14&lt;/span&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;若主协程退出，其他任务被迫终止。没有主协程，新协程也不进行。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Golang八股文</title>
      <link>https://tech.jamaisvu.cn/posts/golang-basic-knowledges/</link>
      <pubDate>Wed, 22 Apr 2026 04:24:04 +0800</pubDate>
      <guid>https://tech.jamaisvu.cn/posts/golang-basic-knowledges/</guid>
      <description>&lt;p&gt;本文持续更新&lt;/p&gt;
&lt;h2 id=&#34;堆栈&#34;&gt;堆、栈&lt;/h2&gt;
&lt;p&gt;它们是程序运行时，两块&lt;strong&gt;用途完全不同&lt;/strong&gt;的内存区域。&lt;/p&gt;
&lt;h3 id=&#34;栈stack-函数的临时小抽屉&#34;&gt;栈（Stack）—— 函数的临时小抽屉&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;每个函数运行时，都会在栈上占一小块空间；&lt;/li&gt;
&lt;li&gt;函数里的&lt;strong&gt;局部变量、参数&lt;/strong&gt;默认都往栈上放；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;函数一结束，栈空间自动清空，变量直接销毁&lt;/strong&gt;；&lt;/li&gt;
&lt;li&gt;速度极快，几乎零开销；&lt;/li&gt;
&lt;li&gt;不需要 GC 垃圾回收。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特点：&lt;strong&gt;自动申请、自动释放，快、小、临时。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;堆heap-全局公共大仓库&#34;&gt;堆（Heap）—— 全局公共大仓库&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;一块共享的大内存；&lt;/li&gt;
&lt;li&gt;放那些&lt;strong&gt;函数结束后还需要活着&lt;/strong&gt;的变量；&lt;/li&gt;
&lt;li&gt;不会自动销毁，靠 Go 的 GC 来回收；&lt;/li&gt;
&lt;li&gt;分配慢、寻址慢、有 GC 开销。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特点：&lt;strong&gt;手动 / 编译器决定分配，GC 回收，慢、大、持久。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&#34;在栈还是堆&#34;&gt;在栈还是堆&lt;/h3&gt;
&lt;p&gt;直接用 Go 自带的&lt;strong&gt;逃逸分析命令&lt;/strong&gt;看：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1&lt;/span&gt;&lt;span&gt;go build -gcflags&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;-m&amp;#34;&lt;/span&gt; main.go
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;输出里会出现两种关键行：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;does not escape&lt;/code&gt; → 变量在 &lt;strong&gt;栈&lt;/strong&gt; 上&lt;/li&gt;
&lt;li&gt;&lt;code&gt;escapes to heap&lt;/code&gt; → 变量逃逸到 &lt;strong&gt;堆&lt;/strong&gt; 上&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;slice&#34;&gt;slice&lt;/h2&gt;
&lt;h3 id=&#34;数据结构&#34;&gt;数据结构&lt;/h3&gt;
&lt;p&gt;slice是引用类型，共享内存地址
&lt;img loading=&#34;lazy&#34; src=&#34;https://raw.githubusercontent.com/grayfalcon666/OSS-FOR-PICGO2/main/20260325001017658.png&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;切片扩容&#34;&gt;切片扩容&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;只有append才会触发扩容&lt;/strong&gt;！手动make只是新建切片。&lt;/p&gt;
&lt;p&gt;扩容会&lt;strong&gt;彻底替换底层数组&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;计算新的容量（按增长规则）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在堆上新建一个更大的底层数组&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;把旧数组的所有数据&lt;strong&gt;完整拷贝&lt;/strong&gt;到新数组&lt;/li&gt;
&lt;li&gt;切片指针指向新数组，更新 &lt;code&gt;len&lt;/code&gt;/&lt;code&gt;cap&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;旧数组如果没有其他引用，会被 &lt;strong&gt;GC 自动回收&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id=&#34;容量增长规则go-118-最新版&#34;&gt;容量增长规则（Go 1.18+ 最新版）&lt;/h5&gt;
&lt;p&gt;小切片快速扩容，大切片平缓扩容，避免内存浪费&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
