我試圖理解一個池庫代碼,當實體化一個池結構時,呼叫一個名為 的函式startCleanerLocked(t Duration),在這個函式中,有一個空select...case...default...代碼塊,我不明白這個代碼塊的效果是什么。
Pool Interface是:
// Pool interface.
type Pool interface {
Get(ctx context.Context) (io.Closer, error)
Put(ctx context.Context, c io.Closer, forceClose bool) error
Close() error
}
List Struct實施Pool Interface,
type List struct {
// New is an application supplied function for creating and configuring a
// item.
//
// The item returned from new must not be in a special state
// (subscribed to pubsub channel, transaction started, ...).
New func(ctx context.Context) (io.Closer, error)
// mu protects fields defined below.
mu sync.Mutex
cond chan struct{}
closed bool
active int
// clean stale items
cleanerCh chan struct{}
// Stack of item with most recently used at the front.
idles list.List
// Config pool configuration
conf *Config
}
創建新池時,startCleanerLocked(t Duration)呼叫函式:
// NewList creates a new pool.
func NewList(c *Config) *List {
// check Config
if c == nil || c.Active < c.Idle {
panic("config nil or Idle Must <= Active")
}
// new pool
p := &List{conf: c}
p.cond = make(chan struct{})
p.startCleanerLocked(time.Duration(c.IdleTimeout))
return p
}
在 中startCleanerLocked(t Duration),有一個select...case...default:
// startCleanerLocked
func (p *List) startCleanerLocked(d time.Duration) {
if d <= 0 {
// if set 0, staleCleaner() will return directly
return
}
if d < time.Duration(p.conf.IdleTimeout) && p.cleanerCh != nil {
select {
case p.cleanerCh <- struct{}{}:
default:
}
}
// run only one, clean stale items.
if p.cleanerCh == nil {
p.cleanerCh = make(chan struct{}, 1)
go p.staleCleaner()
}
}
這個代碼塊的效果是什么:
select {
case p.cleanerCh <- struct{}{}:
default:
}
好像沒什么可做的...
而在 中staleCleaner(),也有同樣的空select..case...case,也無法理解它的作用:
// staleCleaner clean stale items proc.
func (p *List) staleCleaner() {
ticker := time.NewTicker(100 * time.Millisecond)
for {
select {
case <-ticker.C:
case <-p.cleanerCh: // maxLifetime was changed or db was closed.
}
p.mu.Lock()
if p.closed || p.conf.IdleTimeout <= 0 {
p.mu.Unlock()
return
}
for i, n := 0, p.idles.Len(); i < n; i {
e := p.idles.Back()
if e == nil {
// no possible
break
}
ic := e.Value.(item)
if !ic.expired(time.Duration(p.conf.IdleTimeout)) {
// not need continue.
break
}
p.idles.Remove(e)
p.release()
p.mu.Unlock()
ic.c.Close()
p.mu.Lock()
}
p.mu.Unlock()
}
}
uj5u.com熱心網友回復:
select {
case p.cleanerCh <- struct{}{}:
default:
}
這是一個非阻塞select陳述句。(因為有default:案例)
如果在通道的另一端有一個接收器 goroutine p.cleanerCh,即當前有一個 goroutine 在接收操作中“等待” <-p.cleanerCh,則case p.cleanerCh <- struct{}{}立即執行它,這有效地解除了接收操作<-p.cleanerCh的阻塞,然后 goroutine 可以繼續執行任何操作宣告如下。
如果沒有接收者 goroutine,那么default:case 會立即執行,并且周圍的startCleanerLocked函式可以繼續執行陳述句后面的任何select陳述句。
select {
case <-ticker.C:
case <-p.cleanerCh: // maxLifetime was changed or db was closed.
}
這是一個阻止select宣告。(因為沒有default:案例)
該select陳述句阻塞for回圈,直到兩個通信案例之一準備好接收。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/424131.html
