欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文詳解Go語言中對象池的正確打開方式

 更新時間:2025年02月07日 08:18:31   作者:燭陰  
對象池是一種設(shè)計模式,它維護一組已經(jīng)創(chuàng)建好的對象,當(dāng)需要使用對象時,直接從對象池中獲取,使用完畢后再放回對象池,而不是頻繁地創(chuàng)建和銷毀對象,下面我們就來看看Go語言中對象池的具體使用吧

什么是對象池

對象池是一種設(shè)計模式,它維護一組已經(jīng)創(chuàng)建好的對象,當(dāng)需要使用對象時,直接從對象池中獲取,使用完畢后再放回對象池,而不是頻繁地創(chuàng)建和銷毀對象。 這樣可以顯著減少 GC 的壓力,提高程序的性能。

為什么不用 sync.Pool

sync.Pool 是 Go 標(biāo)準(zhǔn)庫提供的對象池實現(xiàn),但它有一些限制:

  • GC 不確定性: sync.Pool 中的對象可能會被 GC 回收,導(dǎo)致每次獲取對象都需要重新創(chuàng)建,失去了對象池的意義。
  • 適用場景有限: sync.Pool 更適合于臨時對象的復(fù)用,對于需要長期存在的對象,效果不佳。
  • 控制力不足: 無法精確控制對象池的大小和對象的生命周期。

因此,在某些場景下,我們需要自定義對象池,以獲得更高的性能和控制力。

手擼對象池:原理與實現(xiàn)

下面,我們就來手擼一個簡單的對象池,并分析其原理。

1. 定義對象池結(jié)構(gòu)體

package main

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

type Pool struct {
	objects chan interface{}   // 使用 channel 存儲對象
	factory func() interface{} // 創(chuàng)建對象的工廠函數(shù)
	mu      sync.Mutex         // 保護對象池
}

var g_index int = 0

func NewPool(size int, factory func() interface{}) *Pool {
	if size <= 0 {
		panic("對象池大小必須大于 0")
	}
	pool := make(chan interface{}, size)
	for i := 0; i < size; i++ {
		pool <- factory() // 預(yù)先創(chuàng)建對象并放入對象池
	}
	return &Pool{
		objects: pool,
		factory: factory,
	}
}

func (p *Pool) Get() interface{} {
	select {
	case obj := <-p.objects:
		return obj // 從對象池中獲取對象
	default:
		// 對象池為空,創(chuàng)建新對象
		fmt.Println("create new object")
		p.mu.Lock()
		defer p.mu.Unlock()
		return p.factory()
	}
}

func (p *Pool) Put(obj interface{}) error {
	select {
	case p.objects <- obj: // 對象放回對象池
		return nil
	default:
		// 對象池已滿,丟棄對象
		obj2 := obj.(*MyObject)
		fmt.Println("pool is full, discard object", obj2.index)
		obj = nil
		return errors.New("pool is full")
	}
}

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

type MyObject struct {
	Data  string
	index int
}

func main() {
	// 創(chuàng)建對象工廠
	objectFactory := func() interface{} {
		g_index += 1
		return &MyObject{Data: "Initial Data", index: g_index}
	}

	// 創(chuàng)建對象池,大小為 10
	pool := NewPool(10, objectFactory)

	var wg sync.WaitGroup
	for i := 0; i < 100; i++ {
		wg.Add(1)
		go func(idx int) {
			fmt.Println("pool len:", pool.Len())
			obj := pool.Get().(*MyObject)
			defer func() {
				wg.Done()
				pool.Put(obj)
			}()
			fmt.Println("from :", obj.Data, obj.index, idx)
			time.Sleep(time.Millisecond * 2) // 模擬一些工作
		}(i)
	}
	wg.Wait()
}

代碼解釋:

  • ObjectPool 結(jié)構(gòu)體包含一個 pool channel,用于存儲對象。
  • factory 是一個函數(shù),用于創(chuàng)建新的對象。
  • NewObjectPool 函數(shù)用于創(chuàng)建對象池,并預(yù)先創(chuàng)建指定數(shù)量的對象放入對象池。
  • Get 函數(shù)用于從對象池中獲取對象。如果對象池為空,則調(diào)用 factory 創(chuàng)建新的對象。
  • Put 函數(shù)用于將對象放回對象池。如果對象池已滿,則丟棄對象。
  • 定義了一個 MyObject 結(jié)構(gòu)體,作為對象池中存儲的對象類型。
  • 創(chuàng)建一個 objectFactory 函數(shù),用于創(chuàng)建 MyObject 對象。
  • 創(chuàng)建一個大小為 10 的對象池,并傳入 objectFactory 函數(shù)。
  • 從對象池中獲取對象,修改對象的數(shù)據(jù),然后將對象放回對象池。
  • 再次從對象池中獲取對象,可以看到對象的數(shù)據(jù)已經(jīng)被修改,說明對象被成功復(fù)用。

總結(jié)

通過手擼對象池,我們不僅可以更好地理解對象池的原理,還可以根據(jù)實際需求定制對象池,以獲得更高的性能和控制力。 在需要頻繁創(chuàng)建和銷毀對象的場景下,使用對象池可以顯著提高程序的性能,告別 GC 噩夢!

到此這篇關(guān)于一文詳解Go語言中對象池的正確打開方式的文章就介紹到這了,更多相關(guān)Go對象池內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

  • 使用Go語言編寫一個極簡版的容器Container

    使用Go語言編寫一個極簡版的容器Container

    Docker作為一種流行的容器化技術(shù),對于每一個程序開發(fā)者而言都具有重要性和必要性,因為容器化相關(guān)技術(shù)的普及大大簡化了開發(fā)環(huán)境配置、更好的隔離性和更高的安全性,對于部署項目和團隊協(xié)作而言也更加方便,本文將嘗試使用Go語言編寫一個極簡版的容器
    2023-10-10
  • Go語言學(xué)習(xí)之時間函數(shù)使用詳解

    Go語言學(xué)習(xí)之時間函數(shù)使用詳解

    這篇文章主要為大家詳細介紹了Go語言中時間函數(shù)的使用方法,文中的示例代碼講解詳細,對我們學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下
    2022-04-04
  • golang通過cgo調(diào)用C++庫源碼示例

    golang通過cgo調(diào)用C++庫源碼示例

    這篇文章主要給大家介紹了關(guān)于golang通過cgo調(diào)用C++庫的相關(guān)資料,CGO是GO語言里面的一個特性,CGO屬于GOLANG的高級用法,主要是通過使用GOLANG調(diào)用CLANG實現(xiàn)的程序庫,需要的朋友可以參考下
    2024-02-02
  • golang網(wǎng)絡(luò)通信超時設(shè)置方式

    golang網(wǎng)絡(luò)通信超時設(shè)置方式

    這篇文章主要介紹了golang網(wǎng)絡(luò)通信超時設(shè)置方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang排列組合算法問題之全排列實現(xiàn)方法

    Golang排列組合算法問題之全排列實現(xiàn)方法

    這篇文章主要介紹了Golang排列組合算法問題之全排列實現(xiàn)方法,涉及Go語言針對字符串的遍歷及排列組合相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • golang基于errgroup實現(xiàn)并發(fā)調(diào)用的方法

    golang基于errgroup實現(xiàn)并發(fā)調(diào)用的方法

    這篇文章主要介紹了golang基于errgroup實現(xiàn)并發(fā)調(diào)用,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • go實現(xiàn)文件的創(chuàng)建、刪除與讀取示例代碼

    go實現(xiàn)文件的創(chuàng)建、刪除與讀取示例代碼

    這篇文章主要給大家介紹了關(guān)于go如何實現(xiàn)文件的創(chuàng)建、刪除與讀取的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧
    2019-02-02
  • Go基于struct?tag實現(xiàn)結(jié)構(gòu)體字段級別的訪問控制

    Go基于struct?tag實現(xiàn)結(jié)構(gòu)體字段級別的訪問控制

    本文將會基于這個主題展開,討論Go中的結(jié)構(gòu)體tag究竟是什么,我們該如何利用它,另外,文末還提供了一個實際案例,實現(xiàn)結(jié)構(gòu)體字段級別的訪問,幫助我們進一步提升對struct tag的理解
    2024-02-02
  • Go??import _ 下劃線使用

    Go??import _ 下劃線使用

    這篇文章主要為大家介紹了Go??import下劃線_使用小技巧,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • 最新評論