golang的pool在公共组件里的使用

博主vx: haitangyijiusu 。很高兴认识你!偶尔带huo,都是精挑细选信得过的产品,欢迎来支持,期待和您相遇!  

1、part1 一个例子

   

 p := pool.Get().(*Person)
    fmt.Printf("第一次从pool里拿对象, %+v \n", p)
    p.Name = "HanMeiMei"
    pool.Put(p)
    fmt.Printf("pool里已经有一个对象, %+v \n", pool.Get().(*Person))
    fmt.Printf("pool里已经没有对象了, %+v \n", pool.Get().(*Person))
    L()

   2、part2 golang里fmt.Printf如何使用sync.Pool

fmt.Printf中Printf对应的函数是:


 

        func Printf(format string, a ...interface{}) (n int, err error) {
            return Fprintf(os.Stdout, format, a...)
        }

        继续看Fprintf函数:

        func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
            p := newPrinter()
            p.doPrintf(format, a)
            n, err = w.Write(p.buf)
            p.free()
            return
        }

        Fprintf第一个参数是io.Writer,Printf函数里传的是os.Stdout,相当于直接输出到标准输出。这里的newPrinter就是调用的Pool,
        拿到pp指针之后,首先是做了一些format操作。并且将p.buf的内容写到w,调用free()函数将p重新归还到pool里。归还之前将p的部分字段重置,以便于其它代码再次拿到这个对象时是“干净”的。

 其中newPrinter对应的函数体是
      

  func newPrinter() *pp {
            p := ppFree.Get().(*pp)
            p.panicking = false
            p.erroring = false
            p.wrapErrs = false
            p.fmt.init(&p.buf)
            return p
        }

函数体里ppFree是一个变量,对应一个sync.Pool
      

  var ppFree = sync.Pool{
            New: func() interface{} { return new(pp) },
        }

结构体pp保存了一个打印对象的状态并且被sync.Pool重用以防止出现内存分配瓶颈。

接下来我们看一下pool_test.go的TestPoolNew函数 在src/sync/pool_test.go
            

func TestPoolNew(t *testing.T) {
                // disable GC so we can control when it happens.
                // 首先设置了GC=-1,就是不去做GC
                defer debug.SetGCPercent(debug.SetGCPercent(-1))

                i := 0
                p := Pool{
                    New: func() interface{} {
                        i++
                        return i
                    },
                }

                // 此时pool里为空,连续调用两次Get,会返回1、2
                if v := p.Get(); v != 1 {
                    t.Fatalf("got %v; want 1", v)
                }
                if v := p.Get(); v != 2 {
                    t.Fatalf("got %v; want 2", v)
                }

                // 防止goroutine被抢占,目的是保护接下来的Put和Get操作都是同一个P的池子
                Runtime_procPin()
                p.Put(42)
                if v := p.Get(); v != 42 {
                    t.Fatalf("got %v; want 42", v)
                }
                Runtime_procUnpin()

                if v := p.Get(); v != 3 {
                    t.Fatalf("got %v; want 3", v)
                }
            }


        type PoolDequeue interface {
            PushHead(val interface{}) bool
            PopHead() (interface{}, bool)
            PopTail() (interface{}, bool)
        }

PoolDequeue 是一个双端队列,可以从头入队元素也可以从头、尾出队元素。

 3、 gin框架也用到了sync.Pool


    github.com\gin-gonic\gin\gin.go

func New() *Engine {
    ...
    engine.pool.New = func() interface{} {
            return engine.allocateContext()
        }
    }

    func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
        c := engine.pool.Get().(*Context)
        c.writermem.reset(w)
        c.Request = req
        c.reset()

        engine.handleHTTPRequest(c)

        engine.pool.Put(c)
    }
    


    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值