golang优雅代码【lock实现】
本文代码风格来源参考
database/sql
包
更加深刻理解go语言圣经中函数是一等公民
1.局部锁
database/sql
源码中使用 withLock(dc, func(){...})
方法实现局部锁,完美利用了 golang
的 defer
关键字对 入参dc
进行加锁解锁,感觉实现很优雅
func (db *DB) queryDC(ctx, txctx context.Context, dc *driverConn, releaseConn func(error), query string, args []any) (*Rows, error) {
queryerCtx, ok := dc.ci.(driver.QueryerContext)
...
if ok {
...
withLock(dc, func() {
// do something ...
})
...
}
...
return rows, nil
}
1.1 具体实现方式
- 首先定义
driverConn
封装sync.Mutex
,实现sync.Locker
接口
type driverConn struct {
db *DB
...
sync.Mutex // guards following
}
- 定义函数
withLock
,接收sync.Locker
,func()
入参,在内部实现获取/释放锁,并执行对应函数
// withLock runs while holding lk.
func withLock(lk sync.Locker, fn func()) {
lk.Lock()
defer lk.Unlock() // in case fn panics
fn()
}
- 使用该方式实现锁
func (db *DB) queryDC(ctx context.Context, dc *driverConn) (*Rows, error) {
...
// 获取&释放锁
withLock(dc, func() {
// do something ...
})
...
return rows, nil
}
- 对比普通方式(非常容易忘记释放锁,并且还要考虑errror)
func (db *DB) queryDC(ctx context.Context, dc *driverConn) (*Rows, error) {
...
// 获取&释放锁
dc.Lock()
// do something ...
dc.Unlock()
...
return rows, nil
}