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

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

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

1.字符串高效拼接

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

1.1 常見的字符串拼接

+號

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 字符串拼接測試

定義一個隨機字符串生成函數(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)
}

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

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

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

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

其次是strings.builder

然后是bytes.buffer

緊接著是 []byte方式

1.3 推薦

一般來說,選擇使用string.Builder方式來進行拼接。

其次,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)存使用也會少一半。

2.相關(guān)原理

2.1 + 號

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

2.2 strings.Builder 與 bytes.Buffer

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

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

bytes.Buffer 內(nèi)存采用[]byte,其內(nèi)部有控制增長的算法,最小申請空間就為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)字符串時,需要重新構(gòu)造string對象;而Builder 返回的string 對象則直接復(fù)用Builder 底層的buf。

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

相關(guān)文章

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

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

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

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

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

    Go語言單鏈表實現(xiàn)方法

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

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

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

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

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

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

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

    golang 獲取明天零點的時間戳示例

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

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

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

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

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

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

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

最新評論

思茅市| 明水县| 浪卡子县| 个旧市| 沭阳县| 抚顺市| 鞍山市| 通榆县| 无锡市| 探索| 阿拉善右旗| 安陆市| 梅河口市| 阳朔县| 鸡泽县| 蓝田县| 大余县| 吴旗县| 石景山区| 甘南县| 平邑县| 永州市| 都安| 扬州市| 龙海市| 诸城市| 克什克腾旗| 台南县| 大名县| 枞阳县| 大同县| 九寨沟县| 岗巴县| 弥勒县| 博爱县| 瑞金市| 当阳市| 松原市| 福贡县| 崇州市| 巨野县|