• Go语言初始化变量的几种方法


    预先初始化

    在外部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())
    }
    
    
  • 相关阅读:
    记录学生的日常
    el表达式与jstl的用法
    学习心得——袁康凯
    学习心得——刘文瑞
    学习心得——高婕
    学习心得——张坤鹏
    Mysql中文乱码 小强斋
    面试题>字符串匹配 小强斋
    选秀节目打分 小强斋
    面试题>字符串匹配 小强斋
  • 原文地址:https://www.cnblogs.com/chenqionghe/p/13947818.html
Copyright © 2020-2023  润新知