共 6 篇文章
用本地 Stub 解决 Go Proto 冲突
在 Go Monorepo 项目中,引入一个内部 RPC 依赖本该是一件简单的事——加一行 require,配一个 replace,代码编译通过,似乎万事大吉。但服务一启动,直接 panic:
panic: proto: file "validate/validate.proto" is already registered
panic: proto: file "common.proto" has a name conflict over trpc.myservice.common.Team两个 panic,两个不同的 proto namespace 冲突。这是 Go protobuf 生态中一个经典的「传递依赖地狱」问题。
本文记录一次真实问题的根因分析和解决方案:如何通过手写一个本地精简 Stub,以最小代码代价绕过 proto 注册机制,彻底消除冲突。
google.protobuf.Value 用法与最佳实践
在 Go 后端开发中,google.protobuf.Value 是一个经常被提及但容易被误用的类型。它属于 Protobuf 的 Well-Known Types(内置类型),设计初衷是解决动态类型问题——即在静态的 message 定义中承载任意的 JSON 兼容数据。
本文从 Go 后端开发者的视角出发,系统讲解 Value 的设计理念、Golang 实战用法,以及常见的最佳实践和避坑指南。
Go 语言 Goroutine 泄露:实战案例分析与排查指南
在 Go 语言开发中,Goroutine 泄露是一个非常隐蔽但致命的问题。它通常发生在一个 Goroutine 被启动后,因为某种逻辑阻塞(比如等待一个永远不会关闭的 Channel 或获取不到锁)而永远无法结束,导致内存逐渐耗尽。
和内存泄漏不同,Goroutine 泄露更难发现——因为 Goroutine 本身占用很小(通常只有几 KB),但成千上万个泄露的 Goroutine 会形成"蚂蚁搬家"效应,最终拖垮整个服务。
本文将分享 4 个实战中非常典型的 Goroutine 泄露案例,并提供排查工具和预防原则。
Go 1.26 栈内存优化:深入理解 slice 的栈分配与逃逸
Go 语言以高效的垃圾回收(GC)著称,但在追求极致性能的路上,内存分配始终是绕不开的话题。2026年2月发布的 Go 1.26 带来了一个重要的编译器优化:现在可以在更多情况下将 slice 的后备存储分配在栈上,而不是堆上。
这意味着当你在函数内创建一个 slice 时,如果它不会逃逸出函数作用域,Go 1.26 会直接把它放在栈上,无需经过堆分配。这不仅减少了 GC 压力,还提升了缓存局部性,是一个"免费"的性能提升。本文将深入讲解栈与堆的区别、逃逸分析的原理,以及如何写出更高效的 Go 代码。
Golang 值传递与引用传递深度解析
在 Golang 中,函数之间传递变量时总是以值的方式传递的。无论是 int、string、bool、array 这样的内置类型,还是 slice、map、channel 这样的引用类型,在函数间传递变量时,都是以值的方式传递。
Go map 底层换用 Swiss Table 性能提升近 50%
在 2024 年 11 月 5 日的 Go compiler and runtime meeting notes 中,我们注意到一个重要信息:来自字节的一位工程师在两年多前提出的「使用 Swiss table 重新实现 Go map」的建议即将落地,该 issue 已经被纳入 Go 1.24 里程碑。