前几天刷 Go 的源码,看到社区新提的一个 unique 包(还在实验阶段),当时第一反应是:“诶,这不就是字符串去重那点事吗?”但后来仔细一看,才发现它背后其实是在搞一个挺巧妙的“字符串内部化”机制。
说白了,这玩意的目标就是——让相同的字符串在内存里只保存一份。
举个特别接地气的例子:
s1 := "hello"
s2 := "he" + "llo"
fmt.Println(&s1 == &s2) // false
你可能以为这俩字符串长得一模一样,就该是同一个地址,但其实不是。 Go 的字符串是不可变的,但每次拼接、转换都会生成新的底层数组。对于一个 web 服务来说,这种重复在内存里浪费得不行。
于是,Go 团队在想办法“内部化”字符串,也就是:相同内容的字符串,在内存里只留一份拷贝,谁用都引用它。
那个 unique 包是干嘛的?
unique 其实是 Go 团队搞的一个新实验包(位于 golang.org/x/exp/unique),里面有个很核心的结构——unique.String。
它的用法超级简单:
package main
import (
"fmt"
"golang.org/x/exp/unique"
)
func main() {
interner := unique.NewStringInterner()
a := interner.Intern("hello")
b := interner.Intern("hello")
fmt.Println(a == b) // true
}
第一次调用 Intern("hello") 时,它会在内部的哈希表里注册 "hello"; 第二次再来相同的字符串时,它就直接返回同一个指针引用,不再分配新的字符串内存。
这就是所谓的 字符串内部化(string interning)。
那这玩意儿到底能省多少?
我前两天正好在公司项目上测了下,我们有个接口,每次返回的 JSON 数据都带一堆相同的键,比如 "user_id", "status", "created_at" 这种。
普通情况下,经过几千次请求后,内存占用在 400MB 左右。 我用一个简易的 intern 机制后(其实就是个 map[string]string),内存直接掉到了 270MB。
大概省了 30% 多的内存。对于高频请求服务,这可不是小数目。
自己撸个简单版
其实实现起来也不难,用 Go 自带的 sync.Map 一把梭就行:
package main
import (
"sync"
)
type StringPool struct {
pool sync.Map
}
func (p *StringPool) Intern(s string) string {
if v, ok := p.pool.Load(s); ok {
return v.(string)
}
p.pool.Store(s, s)
return s
}
这段代码就是一个最简单的内部化字符串池。 核心逻辑很朴素:如果字符串已经存在,就复用;如果没有,就放进去。
当然这也有点小问题,比如这个 sync.Map 永远不会清理老数据,容易变成“内存黑洞”,所以用在高频场景时要加一些清理机制。
unique 包的优势在哪儿?
unique 比自己手写那种 map 要聪明多了。它在内部做了很多小优化,比如:
-
避免内存碎片化 -
用原子操作保证并发安全 -
控制哈希表扩容策略
而且它支持不只是字符串,将来还可能支持其他类型(比如 slice、结构体等)做唯一化。
字符串内部化其实挺有门道
其实不止 Go,像 Java 的 String.intern() 也是干同样的事,只不过它是 JVM 层面管理的。 Go 这边没虚拟机,全靠自己实现。
但有个细节要注意:内部化并不等于压缩,也不等于 deduplication。它只是让“相同值的引用”统一到一个内存块上,不改变字符串的内容,也不会让 GC 更复杂。
如果你场景是那种频繁创建相同字符串的,比如日志解析、模板渲染、协议转换之类的,内部化会立竿见影。 但如果你的字符串本来就五花八门、随机分布,那用 intern 反而浪费时间。
实际使用的建议
-
别滥用。 不要为了省几 MB 到处 intern,反而搞出更大的锁竞争。 -
集中封装。 在解析、反序列化这种阶段做统一的 intern,比业务层到处用强多了。 -
慎用全局池。 尽量按模块分池,用完可清理。
小结
总的来说,unique 包是 Go 在运行时优化方向上的一个小尝试——它不是语法糖,而是帮你更聪明地管内存。
字符串内部化这事其实特别像“人名去重”: 你别到处都存一个“张三”的拷贝,系统里有一个张三就够了,大家都引用他。
如果你最近在搞大规模文本、日志、配置解析的系统,真的可以试试 unique 或者自己实现一个轻量 intern 池。 省内存这事,不是玄学,是真香。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
🔥虎哥私藏精品🔥
虎哥作为一名老码农,整理了全网最全《GO后端开发资料合集》。总量高达650GB,点击下方公众号回复关键字 go全部免费领取

