Golang中Panic的捕获和处理机制

golang生态的错误处理机制和常见的面向对象语言不尽相同。通常情况下,我们可以将panic和recover机制结合起来处理程序运行期间发生的异常错误。 不过这也不是万能的,在语言层面有一些致命的错误是无法被recover捕获的。 本篇文章将会介绍常见的可恢复和不可恢复两大类Pani...

六月 4, 2025 · 2 分钟 · 822 字 · ZhangYong

Golang GC

相关概念 栈对象:指分配在函数调用栈(goroutine stack)上的内存,通常是局部变量(如基本类型、结构体、数组等),它们的生命周期与所属的函数调用绑定,函数返回时被自动回收,无需垃圾回收(GC)干预。 堆对象:指分配在全局堆(heap)上的内存,它们的生命周期由垃圾回收器(G...

四月 3, 2025 · 5 分钟 · 2374 字 · ZhangYong

Golang GMP模型

什么是GMP G(Goroutine) G 是调度的基本单位,由 Go 运行时管理,比 OS 线程更轻量代表goroutine,主要保存状态信息以及寄存器的值。 当 goroutine 被调离 CPU 时,调度器负责把 CPU 寄存器的值保存在 g 对象的成员变量之中。 当 goroutine 被调度起来运行时,调度器又负责把 g 对象的成员变量所保存的寄存器值恢...

三月 28, 2025 · 6 分钟 · 3001 字 · ZhangYong

Golang 底层实现之sync.map

之前在文章《Golang 底层实现之map》里介绍过map在高并发场景下赋值or更新时会检查其标志位flags,当有其他协程在进行“写”操作时会触发panic。 通常为了避免程序出现预期之外的并发读写问题,我们会对map进行加锁保护,或者直接使用官方提供的并发安全map——sync....

三月 19, 2025 · 4 分钟 · 1695 字 · ZhangYong

Golang 原生包之Context

首先要说的是context/context.go源码是一个非常值得学习的实现案例,非常建议阅读源码。 其次关于context的功能简单点可以一言以蔽之: 「context 用来解决 goroutine 之间退出通知、元数据传递的功能。」 具体来说,context 提供了以下能力: 退出通知:通过 context 的取消机制,可...

二月 24, 2025 · 9 分钟 · 4089 字 · ZhangYong

Golang Channel

之前写过一篇文章 《关于对「Don’t communicate by sharing memory, share memory by communicating」的理解》 ,在里面介绍了我对Golang CSP设计理念中「通信」概念的理解。 所以,与前者不同的是,本篇更注重Channel相关底层实现的探索。 数据结构 type hchan struct { qcount uint // 当前队列中的元素数量 dataqsiz uint // chan...

二月 10, 2025 · 9 分钟 · 4477 字 · ZhangYong

Golang 接口(Interface)

一则简单的例子 type IGreeting interface { sayHello() } func sayHello(i IGreeting) { i.sayHello() } type Go struct {} func (g Go) sayHello() { fmt.Println("Hi, I am GO!") } type PHP struct {} func (p PHP) sayHello() { fmt.Println("Hi, I am PHP!") } func main() { golang := Go{} php := PHP{} sayHello(golang) sayHello(php) } 如何通过接口实现多态 多态的字面意思是“多种形态”。在编程中,它指的是: 同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。 通过多态,程序可以在运行时根...

二月 6, 2025 · 7 分钟 · 3443 字 · ZhangYong

Golang 底层实现之map

Map的实现原理 golang 的 map 底层是哈希表查找,平均查找效率是 O(1),最差是 O(N) go源码 在源码中,表示 map 的结构体是 hmap,它是 hashmap 的“缩写”: // A header for a Go map. type hmap struct { count int // 元素个数,调用 len(map) 时,直接返回此值 flags uint8 B uint8 // buckets 的对数 log_2 noverflow uint16 // overflow 的 bucket 近似数,做扩容决策II的判断 hash0 uint32 // hash seed buckets unsafe.Pointer // 指向 buckets 数组...

十二月 20, 2024 · 14 分钟 · 6600 字 · ZhangYong

Golang Redis分布式锁实现

package lock import ( "context" "errors" "cache" "time" "github.com/go-redis/redis/v8" "github.com/google/uuid" ) const ( DefaultExpirationTime = 5 * time.Second RenewInterval = DefaultExpirationTime / 2 // 续租间隔为锁过期时间的一半 LuaCheckAndDelKey = ` if(redis.call('get',KEYS[1])==ARGV[1]) then return redis.call('del',KEYS[1]) else return 0 end ` LuaCheckAndRenewKey = ` if(redis.call('get',KEYS[1])==ARGV[1]) then return redis.call('expire',KEYS[1],ARGV[2]) else return 0 end ` ) type RedisLock struct { key string val string expiration time.Duration cli *redis.Client script *redis.Script // 用于解锁的 Lua 脚本 renewScript *redis.Script // 用于续租的 Lua 脚本 stopChan chan struct{} // 用于停止续租 goroutine } func NewRedisLock(key string) *RedisLock { val := uuid.New().String() return &RedisLock{ key: key, val: val, expiration: DefaultExpirationTime, cli: cache.RedisV8Client, script: redis.NewScript(LuaCheckAndDelKey), renewScript: redis.NewScript(LuaCheckAndRenewKey), stopChan: make(chan struct{}), } } func (r *RedisLock) Lock(ctx context.Context)...

八月 14, 2024 · 1 分钟 · 329 字 · ZhangYong

脚本拉取pprof数据分析服务cpu偶发突刺问题

最近工作中遇到一个比较奇怪的问题,容器化部署的服务container会在不定时偶发CPU突刺,从而引发频繁动态扩容。 服务是go开发的,所以准备让服务提供pprof接口来分析CPU的使用情况。 但由于CPU突刺是不定时的,并且网关一般都有请求读写超时配置。 所以我们不能一次拉取太长时间...

六月 19, 2024 · 2 分钟 · 753 字 · ZhangYong