最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golong字符串拼接性能優(yōu)化及原理介紹

 更新時(shí)間:2023年04月04日 11:11:10   作者:qq_42170897  
最近在做性能優(yōu)化,有個(gè)函數(shù)里面的耗時(shí)特別長(zhǎng),看里面的操作大多是一些字符串拼接的操作,而字符串拼接在 golang 里面其實(shí)有很多種實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于Golang語(yǔ)言如何高效拼接字符串的相關(guān)資料,需要的朋友可以參考下

1.字符串高效拼接

go 字符串是不可修改的,所謂字符串拼接就是創(chuàng)建新的字符串對(duì)象。如果代碼中存在大量的字符串拼接,那么性能將會(huì)存在影響。

1.1 常見的字符串拼接

+號(hào)

func plusConcat(n int, s string) string {
	var d string
	for i := 0; i < n; i++ {
		d += s
	}
	return d
}

格式化

func sprintfConcat(n int, s string) string {
	var d string
	for i := 0; i < n; i++ {
		d = fmt.Sprintf("%s%s", d, s)
	}
	return d
}

strings.Builder

func builderConcat(n int, s string) string {
	var sb = new(strings.Builder)
	for i := 0; i < n; i++ {
		sb.WriteString(s)
	}
	return sb.String()
}

bytes.Buffer

func bufferConcat(n int, s string) string {
	var bb = new(bytes.Buffer)
	for i := 0; i < n; i++ {
		bb.WriteString(s)
	}
	return bb.String()
}

[]byte

func byteConcat(n int, s string) string {
	var b = make([]byte, 0)
	for i := 0; i < n; i++ {
		b = append(b, s...)
	}
	return string(b)
}

預(yù)分配[]byte

func preByteConcat(n int, s string) string {
	var b = make([]byte, 0, n*len(s))
	for i := 0; i < n; i++ {
		b = append(b, s...)
	}
	return string(b)
}

1.2 字符串拼接測(cè)試

定義一個(gè)隨機(jī)字符串生成函數(shù):

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
func randomString(n int) string {
	b := make([]byte, n)
	for i := range b {
		b[i] = letterBytes[rand.Intn(len(letterBytes))]
	}
	return string(b)
}

對(duì)上述6中字符串拼接函數(shù)進(jìn)行基準(zhǔn)測(cè)試:

func benchmark(b *testing.B, f func(int, string) string) {
	var str = randomString(10)
	for i := 0; i < b.N; i++ {
		f(10000, str)
	}
}
func BenchmarkPlusConcat(b *testing.B)    { benchmark(b, plusConcat) }
func BenchmarkSprintfConcat(b *testing.B) { benchmark(b, sprintfConcat) }
func BenchmarkBuilderConcat(b *testing.B) { benchmark(b, builderConcat) }
func BenchmarkBufferConcat(b *testing.B)  { benchmark(b, bufferConcat) }
func BenchmarkByteConcat(b *testing.B)    { benchmark(b, byteConcat) }
func BenchmarkPreByteConcat(b *testing.B) { benchmark(b, preByteConcat) }

go test -bench=. test/string -benchmem

毫無疑問 + 和 格式化 兩種方式最耗時(shí),且內(nèi)存分配還多。

性能最好的是預(yù)分配[]byte方式,它只進(jìn)行兩次內(nèi)存分配,其余部分全部在進(jìn)行內(nèi)存拷貝操作。

其次是strings.builder

然后是bytes.buffer

緊接著是 []byte方式

1.3 推薦

一般來說,選擇使用string.Builder方式來進(jìn)行拼接。

其次,strings.Builder 提供了 Grow方法,特殊情況下避免多次內(nèi)存分配。

func builderConcat(n int, s string) string {
	var sb = new(strings.Builder)
	sb.Grow(n * len(s))
	for i := 0; i < n; i++ {
		sb.WriteString(s)
	}
	return sb.String()
}

然后Builder 再與 預(yù)分配的[]byte 比較:

得出:builder 比 預(yù)分配[]byte 少一次內(nèi)存分配,當(dāng)然內(nèi)存使用也會(huì)少一半。

2.相關(guān)原理

2.1 + 號(hào)

+ 性能如此差是因?yàn)間o 字符串本省不可修改,兩個(gè)字符串拼接,那么新構(gòu)造一個(gè)字符串,長(zhǎng)度等與兩個(gè)字符串長(zhǎng)度之和,然后分別將兩個(gè)字符串的內(nèi)容拷貝到新的字符串中。且如果連續(xù)的字符串拼接,就像plusConcat函數(shù),會(huì)產(chǎn)生大量臨時(shí)對(duì)象d,對(duì)GC也是一種壓力。

2.2 strings.Builder 與 bytes.Buffer

2.2.1 內(nèi)部[]byte 增長(zhǎng)方式:

strings.Builder 內(nèi)部采用[]byte存儲(chǔ),初始大小為0,每次寫入是按go 默認(rèn)切片增長(zhǎng)方式拓展底層[]byte的長(zhǎng)度。

bytes.Buffer 內(nèi)存采用[]byte,其內(nèi)部有控制增長(zhǎng)的算法,最小申請(qǐng)空間就為64bytes,在寫入為超過一倍的情況下,是按1一倍空間增加。

64 128 256 512 1024 2048 4096 8192 16384 32768 65536 131072 262144 ...

2.2.2 性能比較

為啥 Buffer 比 Builder 多一次內(nèi)存分配:

Buffer 的String() 方法:

func (b *Buffer) String() string {
	if b == nil {
		// Special case, useful in debugging.
		return "<nil>"
	}
	return string(b.buf[b.off:])
}

Builder 的String() 方法:

// String returns the accumulated string.
func (b *Builder) String() string {
	return unsafe.String(unsafe.SliceData(b.buf), len(b.buf))
}

可以看出,Buffer在轉(zhuǎn)字符串時(shí),需要重新構(gòu)造string對(duì)象;而Builder 返回的string 對(duì)象則直接復(fù)用Builder 底層的buf。

到此這篇關(guān)于Golong字符串拼接性能優(yōu)化及原理介紹的文章就介紹到這了,更多相關(guān)Go字符串拼接內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Golang通脈之?dāng)?shù)據(jù)類型詳情

    Golang通脈之?dāng)?shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之?dāng)?shù)據(jù)類型,在編程語(yǔ)言中標(biāo)識(shí)符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語(yǔ)言中標(biāo)識(shí)符允許由字母數(shù)字和_(下劃線)組成,并且只能以字母和_開頭,更詳細(xì)內(nèi)容請(qǐng)看下面文章吧
    2021-10-10
  • Golang中struct{}和struct{}{}的區(qū)別解析

    Golang中struct{}和struct{}{}的區(qū)別解析

    這篇文章主要介紹了Golang中struct{}和struct{}{}的區(qū)別,通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • Go語(yǔ)言單鏈表實(shí)現(xiàn)方法

    Go語(yǔ)言單鏈表實(shí)現(xiàn)方法

    這篇文章主要介紹了Go語(yǔ)言單鏈表實(shí)現(xiàn)方法,實(shí)例分析了基于Go語(yǔ)言的單鏈表實(shí)現(xiàn)原理與使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-03-03
  • golang語(yǔ)言編碼規(guī)范的實(shí)現(xiàn)

    golang語(yǔ)言編碼規(guī)范的實(shí)現(xiàn)

    這篇文章主要介紹了golang語(yǔ)言編碼規(guī)范的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Go信號(hào)處理如何優(yōu)雅地關(guān)閉你的應(yīng)用

    Go信號(hào)處理如何優(yōu)雅地關(guān)閉你的應(yīng)用

    Go?中的優(yōu)雅關(guān)閉機(jī)制使得在應(yīng)用程序接收到終止信號(hào)時(shí),能夠進(jìn)行平滑的資源清理,通過使用?context?來管理?goroutine?的生命周期,結(jié)合?signal?包捕獲系統(tǒng)信號(hào),你可以在?Go?應(yīng)用中實(shí)現(xiàn)一個(gè)健壯且優(yōu)雅的關(guān)閉過程,對(duì)Go關(guān)閉應(yīng)用相關(guān)操作感興趣的朋友一起看看吧
    2025-01-01
  • Golang 文件操作:刪除指定的文件方式

    Golang 文件操作:刪除指定的文件方式

    這篇文章主要介紹了Golang 文件操作:刪除指定的文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • golang 獲取明天零點(diǎn)的時(shí)間戳示例

    golang 獲取明天零點(diǎn)的時(shí)間戳示例

    今天小編就為大家分享一篇golang 獲取明天零點(diǎn)的時(shí)間戳示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • go語(yǔ)言單元測(cè)試基準(zhǔn)測(cè)試及表驅(qū)動(dòng)測(cè)試示例詳解

    go語(yǔ)言單元測(cè)試基準(zhǔn)測(cè)試及表驅(qū)動(dòng)測(cè)試示例詳解

    這篇文章主要為大家介紹了go語(yǔ)言單元測(cè)試基準(zhǔn)測(cè)試及表驅(qū)動(dòng)測(cè)試示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Golang String字符串類型轉(zhuǎn)Json格式

    Golang String字符串類型轉(zhuǎn)Json格式

    本文主要介紹了Golang String字符串類型轉(zhuǎn)Json格式的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-05-05
  • 詳解Go語(yǔ)言中調(diào)度器的原理與使用

    詳解Go語(yǔ)言中調(diào)度器的原理與使用

    這篇文章主要介紹了Go語(yǔ)言運(yùn)行時(shí)調(diào)度器的實(shí)現(xiàn)原理,其中包含調(diào)度器的設(shè)計(jì)與實(shí)現(xiàn)原理、演變過程以及與運(yùn)行時(shí)調(diào)度相關(guān)的數(shù)據(jù)結(jié)構(gòu),希望對(duì)大家有所幫助
    2023-07-07

最新評(píng)論

永泰县| 荔波县| 花莲县| 连江县| 田阳县| 阿巴嘎旗| 榆中县| 德安县| 蚌埠市| 平远县| 哈尔滨市| 义马市| 西宁市| 绥德县| 水城县| 岳普湖县| 太保市| 古蔺县| 论坛| 武宁县| 石嘴山市| 巴楚县| 梅州市| 淅川县| 葫芦岛市| 沈阳市| 东安县| 子长县| 稷山县| 滕州市| 澄城县| 开江县| 丹江口市| 凤凰县| 阿荣旗| 柳江县| 嵊州市| 韩城市| 沾化县| 梁平县| 枝江市|