Golang简单的对象池

Golang简单的对象池

  • 复用的好处
    • 减少gc压力
    • 减少不必要的内存分配

import (
    "fmt"
    "sync"
)

var bufPool sync.Pool

type buf struct {
    b []byte
}

func main() {
    for {
        var bf *buf
        // 从池中取数据
        v := bufPool.Get()
        if v == nil {
            //若不存在buf,创建新的
            fmt.Println("no buf ,create!")
            bf = &buf{
                b: make([]byte, 10),
            }
        } else {
            // 池里存在buf,v这里是interface{},需要做类型转换
            bf = v.(*buf)
        }
        fmt.Println("使用数据", bf)
        // bf使命完成,放入池中
        bufPool.Put(bf)
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Golang 的内存池使用起来很简单,只需要使用 sync.Pool 包中的 Get 和 Put 方法,就可以在内存池中请求和释放内存块: // 创建一个内存池 pool := &sync.Pool { New: func() interface{} { b := make([]byte, 1024) return &b }, }// 从内存池中请求内存块 buf := pool.Get().(*[]byte)// 使用完毕后,将内存块释放回内存池 pool.Put(buf) ### 回答2: 使用 golang 的内存池可提高性能,减少内存分配的开销,并减轻垃圾回收的负担。下面是一个简单的示例代码: 首先,我们需要导入 "sync" 包用于同步操作,以及 "github.com/oleiade/lane" 包用于实现队列(FIFO)。 ``` import ( "sync" "github.com/oleiade/lane" ) // 定义一个内存池结构 type MemoryPool struct { pool *lane.Queue // 使用队列实现内存池 maxSize int // 内存池的最大容量 lock sync.Mutex // 用于同步操作的锁 } // 初始化内存池 func NewMemoryPool(maxSize int) *MemoryPool { return &MemoryPool{ pool: lane.NewQueue(), // 初始化队列 maxSize: maxSize, // 设置最大容量 } } // 获取一个对象 func (p *MemoryPool) Get() interface{} { p.lock.Lock() // 加锁 defer p.lock.Unlock() if p.pool.Size() > 0 { return p.pool.Dequeue() // 如果池中有可用对象,则出队并返回 } return nil // 池中无可用对象时返回 nil } // 释放一个对象 func (p *MemoryPool) Put(obj interface{}) { p.lock.Lock() // 加锁 defer p.lock.Unlock() if p.pool.Size() < p.maxSize { p.pool.Enqueue(obj) // 如果池未满,则将对象入队 } } ``` 这份代码中,我们创建了一个内存池结构 `MemoryPool`,其中包含一个 `lane.Queue` 类型的队列 `pool`,用于存储已经分配的对象。`maxSize` 属性表示内存池的最大容量。 在 `Get()` 方法中,首先通过加锁操作来保证并发安全。如果内存池中有可用对象,就将对象从队列中出队并返回;否则返回 `nil`。 在 `Put()` 方法中,也通过加锁来保证并发安全。如果内存池未满,就将对象入队。 这样,我们就实现了一个简单golang 内存池。在实际应用中,可以根据具体需求对内存池进行优化和扩展。 ### 回答3: Golang内存池是一种可以提供重复使用的内存资源的机制,可以有效地减少内存分配和回收的开销。以下是一个简单的使用Golang内存池的代码示例: ```go package main import ( "fmt" "sync" ) var pool = sync.Pool{ New: func() interface{} { return make([]byte, 1024) // 初始化一个长度为1024的字节切片 }, } func main() { // 从内存池中获取一个字节切片 data := pool.Get().([]byte) // 断言类型为[]byte // 使用字节切片进行数据操作 copy(data, []byte("Hello, world!")) // 打印字节切片中的数据 fmt.Println(string(data)) // 将字节切片重新放回内存池 pool.Put(data) // 从内存池中获取一个新的字节切片 newData := pool.Get().([]byte) // 此时newData的内容与之前的data相同,可以继续使用 fmt.Println(string(newData)) // 清空内存池 pool.New = nil } ``` 在以上示例中,我们首先创建了一个sync.Pool对象,其New字段是一个匿名函数,用于创建一个长度为1024的字节切片,并将其作为默认的新对象。 接下来,在main函数中,我们通过pool.Get()方法从内存池中获取一个字节切片,并进行数据操作。当我们完成后,通过pool.Put()方法将字节切片重新放回内存池。 对于下一次需要新的字节切片时,我们可以再次调用pool.Get()方法,此时会从内存池中获取之前放回的字节切片,因此可以继续使用。 最后,我们可以通过将pool.New字段设置为nil来清空内存池,使其在下一次pool.Get()时重新生成新的对象。 使用内存池可以避免频繁的内存分配和回收操作,提高程序的性能。不过需要注意的是,内存池中的对象并不是永久存在的,可能会在不同的时间点被回收,因此必要时需要考虑重新分配内存。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值