SoFunction
Updated on 2025-04-11

A detailed explanation of the correct way to open an object pool in Go language

What is an object pool

Object pool is a design pattern that maintains a set of created objects. When using objects, they are directly retrieved from the object pool and put back into the object pool after use, rather than frequently creating and destroying objects. This can significantly reduce the pressure on the GC and improve the performance of the program.

Why not use it

is an object pool implementation provided by the Go standard library, but it has some limitations:

  • GC Uncertainty: Objects in it may be recycled by GC, resulting in the need to be recreated every time the object is retrieved, losing the meaning of the object pool.
  • Limited applicable scenarios: It is more suitable for the reuse of temporary objects, and the effect is not good for objects that need to exist for a long time.
  • Insufficient control:There is no precise control of the size of the object pool and the life cycle of the object.

Therefore, in some scenarios, we need to customize the object pool for higher performance and control.

Hand-pushing object pool: Principle and implementation

Next, let’s take a simple object pool and analyze its principles.

1. Define the object pool structure

package main

import (
	"errors"
	"fmt"
	"sync"
	"time"
)

type Pool struct {
	objects chan interface{}   // Use channel to store objects	factory func() interface{} // Create the factory function of the object	mu               // Protect the object pool}

var g_index int = 0

func NewPool(size int, factory func() interface{}) *Pool {
	if size <= 0 {
		panic("Object pool size must be greater than 0")
	}
	pool := make(chan interface{}, size)
	for i := 0; i < size; i++ {
		pool <- factory() // Pre-create objects and put them in the object pool	}
	return &Pool{
		objects: pool,
		factory: factory,
	}
}

func (p *Pool) Get() interface{} {
	select {
	case obj := <-:
		return obj // Get object from object pool	default:
		// The object pool is empty, create a new object		("create new object")
		()
		defer ()
		return ()
	}
}

func (p *Pool) Put(obj interface{}) error {
	select {
	case  <- obj: // Put the object back to the object pool		return nil
	default:
		// The object pool is full, discard the object		obj2 := obj.(*MyObject)
		("pool is full, discard object", )
		obj = nil
		return ("pool is full")
	}
}

func (p *Pool) Len() int {
	return len()
}

type MyObject struct {
	Data  string
	index int
}

func main() {
	// Create object factory	objectFactory := func() interface{} {
		g_index += 1
		return &MyObject{Data: "Initial Data", index: g_index}
	}

	// Create an object pool with a size of 10	pool := NewPool(10, objectFactory)

	var wg 
	for i := 0; i < 100; i++ {
		(1)
		go func(idx int) {
			("pool len:", ())
			obj := ().(*MyObject)
			defer func() {
				()
				(obj)
			}()
			("from :", , , idx)
			( * 2) // Simulate some work		}(i)
	}
	()
}

Code explanation:

  • ObjectPoolThe structure contains apoolchannel, used to store objects.
  • factoryis a function that creates new objects.
  • NewObjectPoolFunctions are used to create object pools and pre-create a specified number of objects into the object pool.
  • GetFunctions are used to obtain objects from the object pool. If the object pool is empty, callfactoryCreate a new object.
  • PutFunctions are used to put objects back into the object pool. If the object pool is full, the object is discarded.
  • Define aMyObjectStructure, as the object type stored in the object pool.
  • Create aobjectFactoryFunctions for creatingMyObjectObject.
  • Create a pool of object size 10 and pass inobjectFactoryfunction.
  • Get the object from the object pool, modify the object's data, and then put the object back to the object pool.
  • Get the object from the object pool again and you can see that the object's data has been modified, indicating that the object has been successfully reused.

Summarize

By hand-pushing the object pool, we can not only better understand the principle of the object pool, but also customize the object pool according to actual needs to obtain higher performance and control. In scenarios where objects are frequently created and destroyed, using object pools can significantly improve the performance of the program and say goodbye to GC nightmare!

This is the article about this article explaining the correct way to open object pools in Go language. For more related Go object pool content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!