預先初始化
在外部var初始化
package main
import (
"fmt"
"time"
)
var startTime = time.Now()
func main() {
fmt.Println(startTime)
}
在init函數初始化
package main
import (
"fmt"
"time"
)
var startTime time.Time
func init() {
startTime = time.Now()
}
func main() {
fmt.Println(startTime)
}
在main函數執行自定義初始化函數
package main
import (
"fmt"
"time"
)
var startTime time.Time
func initApp() {
startTime = time.Now()
}
func main() {
initApp()
fmt.Println(startTime)
}
延遲加載僅初始化一次(單例)
加鎖實現
雖然達到要求了,但是有性能問題,因為每一次請求者要競爭鎖才能讀取到這個連接
其實創建好連接之后,就不需要鎖的保護了
var connMu sync.Mutex
var conn net.Conn
func getConn() net.Conn {
connMu.Lock()
defer connMu.Unlock()
if conn != nil {
return conn
}
conn,_ = net.DialTimeout("tcp","baidu.com:80",10*time.Second)
return conn
}
func main() {
conn := getConn()
if conn != nil {
panic("conn is nil")
}
}
標准庫Once實現
package main
import (
"net"
"sync"
)
var conn net.Conn
var once sync.Once
func getConn() net.Conn {
var err error
once.Do(func() {
conn, err = net.Dial("tcp", "baidu.com")
})
return conn
}
func main() {
conn := getConn()
if conn != nil {
panic("conn is nil")
}
}
自定義Once實現
Once實現的邏輯有一個缺陷,就是當f函數初始化失敗后,以后就不會再執行了,我們其實可以在Once里加入當f函數不返回error的時候才代表初始化完成了
另外,我們還可以返回Done檢察是否已經初始化完成了
package main
import (
"errors"
"fmt"
"sync"
"sync/atomic"
)
type Once struct {
done uint32
m sync.Mutex
}
func (o *Once) Do(f func() error) error {
if atomic.LoadUint32(&o.done) == 0 {
return o.doSlow(f)
}
return nil
}
func (o *Once) doSlow(f func() error) (err error) {
o.m.Lock()
defer o.m.Unlock()
if o.done == 0 {
if err = f(); err == nil {
defer atomic.StoreUint32(&o.done, 1)
}
}
return err
}
//再加入一個判斷Once是否執行完的方法
func (o *Once) Done() bool {
return atomic.LoadUint32(&o.done) == 1
}
func main() {
var once Once
once.Do(func() error {
fmt.Println("one")
return errors.New("one error")
})
fmt.Println(once.Done())
once.Do(func() error {
fmt.Println("two")
return nil
})
fmt.Println(once.Done())
}