<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>原理 on Tequila's 学习笔记</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/</link><description>Recent content in 原理 on Tequila's 学习笔记</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><copyright>© 2026 Tequila</copyright><atom:link href="https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/index.xml" rel="self" type="application/rss+xml"/><item><title>context</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-c44123ebaf4dac00/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-c44123ebaf4dac00/</guid><description>context 使用场景和用途？
context 主要用来在 goroutine 之间传递上下文信息，比如传递请求的trace_id,以便于追踪全局唯一请求​
另一个用处是可以用来做取消控制，通过取消信号和超时时间来控制子goroutine的退出，防止goroutine泄漏​ 包括：取消信号、超时时间、截止时间、k-v 等。</description></item><item><title>Defer</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-74992bd6fb4778a1/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-74992bd6fb4778a1/</guid><description/></item><item><title>GC</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-f4ff398addf443c6/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-f4ff398addf443c6/</guid><description> V1.3及之前：标记清除算法​ # 完整的标记清除算法需要在进行GC前进行STW，即暂停整个用户程序。这样的话，性能必然很低，很难有人可以接受这种性能损耗
V1.5：三色并发标记法​ # 白色：未被垃圾收集器访问到的对象，也就是潜在的垃圾对象。在回收开始阶段 ，所有对象都标记为白色；在回收结束后，所有白色对象均不可达，其内存将被释放​ 灰色：已被垃圾收集器访问到的对象，但是垃圾收集器需要继续扫描它们的子对象，因为其可能存在指向白色对象的外部指针​ 黑色：已被垃圾收集器访问到的对象，且其引用都已被扫描到，黑色对象中任何一个指针都不可能直接指向白色对象
发生错误：
一个白色对象被黑色对象引用(白色对象被挂在黑色对象下)​ 灰色对象与它之间的可达关系的白色对象遭到破坏(灰色对象同时丢失了该白色对象的引用) 屏障技术： 强三色不变性：不存在黑色对象引用到白色对象的指针，即黑色对象不会指向白色对象，只会指向灰色对象或黑色对象 弱三色不变性：所有被黑色对象引用的白色对象都处于灰色对象的保护状态，黑色对象可以指向的白色对象，但是必须包含一条从灰色对象到这个白色对象的可达路径
插入写屏障（Dijistra Insertion Barrier）​：作用在堆上，栈上仍然是stw 由于指针修改时，指向的新对象要被强制标灰，所以插入写屏障满足强三色不变式，不存在黑色对象引用白色对象的情况了， 因为白色会强制变成灰色 删除写屏障（Yuasa Deletion Barrier）：go未使用 V1.8：混合写屏障机制 #</description></item><item><title>GMP</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-41bc74a3678881d4/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-41bc74a3678881d4/</guid><description/></item><item><title>Map</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-833cda42db400b52/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-833cda42db400b52/</guid><description>哈希表的原理是将多个k-v键值对散列的存储在buckets中，buckets可以理解为一个连续的数组，所以给定一个key/value键值对，我们要将其存储到合适的位置需要经过两步骤：
计算hash值：hash = hashFunc(key) 计算索引位置: index = hash % len(buckets) 哈希冲突 # 解决哈希碰撞一般有两种方式；拉链法和开放寻址法
拉链法 # 开放寻址法 # Map # type hmap struct { count int // 当前存储的键值对数量 flags uint8 // 标志位，用于记录 map 的状态（如是否正在扩容等） B uint8 // 桶数组的大小是 2^B，决定了桶的数量 noverflow uint16 // 记录溢出桶的数量 hash0 uint32 // 哈希种子，防止哈希冲突攻击 buckets unsafe.Pointer // 指向主桶数组的指针 oldbuckets unsafe.Pointer // 扩容时，指向旧桶数组 nevacuate uintptr // 记录扩容的进度，表示已经迁移的桶的索引 extra *mapextra // 存储溢出桶和其他额外信息 } type bmap struct { topbits [8]uint8 keys [8]keytype values [8]valuetype overflow uintptr } // go 1.</description></item><item><title>Slice</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-6cc7e0428177936b/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-6cc7e0428177936b/</guid><description>type slice struct { array unsafe.Pointer len int cap int } 拷贝复制指针，使用同一块内存空间 newcap = oldcap+(oldcap+3*256)/4
检查所需容量：如果所需容量大于当前容量的两倍，则直接扩容到所需容量。 容量小于阈值时：如果当前容量小于阈值（默认 256），则新容量为当前容量的两倍。 容量大于阈值时：当容量超过阈值，扩容系数逐渐从 2 倍过渡到 1.25 倍，具体公式为：</description></item><item><title>String</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-1014e48fb22ff92b/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-1014e48fb22ff92b/</guid><description>type stringStruct struct { str unsafe.Pointer len int } 通过观察字符串的结构定义我们可以发现，其定义中并没有一个表示容量(Cap)的字段，所以意味着字符串类型并不能被扩容，字符换上的写操作包括拼接，追加等等都是通过拷贝来实现的。
string与[]byte的转化原理 # 字符串拼接性能分析 # 方法 说明 + + 拼接 2 个字符串时，会生成一个新的字符串，开辟一段新的内存空间，新空间的大小是原来两个字符串的大小之和，所以每拼接一次就要开辟一段空间，性能较差 Sprintf Sprintf 会从临时对象池中获取一个对象，然后进行格式化操作，最后转换为 string，再释放对象，实现较复杂，性能较差 strings.Builder 底层使用 []byte 存储，转换为字符串时可以复用底层数据。支持预分配内存并自动扩容，因此减少内存分配次数，性能最好 bytes.Buffer 底层使用 []byte，但转换为字符串时不可复用，会重新申请一块内存存放字符串。实现类似 strings.Builder，性能略差 append 直接使用 []byte 的扩容机制，可复用，支持预分配和自动扩容。性能优于 + 和 Sprintf，如果提前分配好内存，性能接近 strings.Builder string.Join strings.Join 性能约等于 strings.Builder，适合已有 string slice 的情况。如果需要先构造 slice，再 Join，则会有额外开销 strings.Builder ≈ string.Join ≈ append &amp;gt; bytes.Buffer &amp;gt; + &amp;gt; fmt.Sprintf func main() { // 1. + 拼接 s1 := &amp;#34;Hello&amp;#34; s2 := &amp;#34;World&amp;#34; result1 := s1 + &amp;#34; &amp;#34; + s2 fmt.</description></item><item><title>Sync.Map</title><link>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-091b4216bef74b3a/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://latnx.github.io/docs/notes/d-205f3859abe469be/d-f7ccae636d10bb41/d-68099c72ea2c86f8/n-091b4216bef74b3a/</guid><description>使用两个map之间的互相配合(一个read map 和 一个dirty map)，来为我们提供一个拥有并发读写能力，并且权衡整体操作性能的hashTable结构
type Map struct {​ // 互斥锁，保证dirty map 和 misses的并发安全​ mu sync.Mutex​ // 无锁化的read map（小林服务器）​ read atomic.Value // readOnly​ // 读写需要加锁的map（诸葛青服务器）​ dirty map[any]*entry​ // 记录有多少次读、删请求 找了诸葛青​ misses int​ }​ type readOnly struct {​ // read map 存放 k-v的实体​ m map[interface{}]*entry​ // 标识是否有 数据缺失，即dirty map里面有 read map中没有的key，就是amended为true​ amended bool​ } 双向数据流转机制 # 大量 key 在 read 中找不到，但在 dirty 中能找到
read = dirty dirty = nil misses = 0 read map获得dirty map全量数据，将dirty map的值直接赋给read map 如果有新的写请求到来，将read map里面的逻辑上存在的数据拷贝到dirty map entry 状态 # type entry struct { p unsafe.</description></item></channel></rss>