溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Golang中字符串拼接問(wèn)題怎么解決

發(fā)布時(shí)間:2023-04-11 15:38:40 來(lái)源:億速云 閱讀:128 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容主要講解“Golang中字符串拼接問(wèn)題怎么解決”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Golang中字符串拼接問(wèn)題怎么解決”吧!

1.概述

Go的字符串是一個(gè)不可改變的數(shù)據(jù)結(jié)構(gòu),這和其他語(yǔ)言如JAVA,C++等的設(shè)定很類似.總體來(lái)說(shuō),有如下五種拼接方式,下面我們將論述各種方式的性能問(wèn)題,以及如何選擇.

Golang中字符串拼接問(wèn)題怎么解決

(golang字符串,內(nèi)存模型)

type StringHeader struct {
	Data uintptr
	Len  int
}

注意:字符串具有不可改變的特性,即便通過(guò)指針等變相操作

	var a string = "old"
	bptr := (*reflect.StringHeader)(unsafe.Pointer(&a))
	dataPtr := (*byte)(unsafe.Pointer(bptr.Data))
	var b = [3]byte{'n', 'e', 'w'}
	*dataPtr = b[0] //報(bào)錯(cuò)
	fmt.Println(bptr)

2.Golang中字符串拼接的方式

方式一、直接+

當(dāng)使用連接符 + 拼接兩個(gè)字符串時(shí),會(huì)生成一個(gè)新的字符串并開(kāi)辟新的內(nèi)存空間,空間大小等于兩個(gè)字符串之和。在訓(xùn)中中時(shí),不斷拼接新的字符串,這樣就會(huì)不斷申請(qǐng)內(nèi)存空間, 性能就會(huì)越來(lái)越差。 所以,在字符串密集拼接場(chǎng)景中,使用 + 會(huì)嚴(yán)重降低性能。包括熱路徑的代碼.

方式二、strings.Builder

func Benchmark_StringsBuilder(b *testing.B) {
	var sb strings.Builder
	for i := 0; i < b.N; i++ {
		sb.WriteString("hello world")
	}
	_ = sb.String()
}

方式三、bytes.Buffer

func Benchmark_BytesBuffer(b *testing.B) {
	var buf bytes.Buffer
	for i := 0; i < b.N; i++ {
		buf.WriteString("hello world")
	}
	_ = buf.String()
}

方式四、fmt.Fprint(&buf,&str)

方式五、strings.Join

性能不是最優(yōu),但在切片的情況下,可以用來(lái)拼接

3.總結(jié)

Benchmark_StringAdd Benchmark_StringAdd-8 117806 127059 ns/op Benchmark_BytesBuffer Benchmark_BytesBuffer-8 38938282 25.88 ns/op Benchmark_StringsBuilder Benchmark_StringsBuilder-8 57249450 18.53 ns/op

3.1 性能方面,strings.Builder 比 bytes.Buffer 快差不多 20%,

原因:strings.Builder 和 bytes.Buffer 底層都是一個(gè) []byte,但是 bytes.Buffer 轉(zhuǎn)換字符串時(shí)會(huì)重新申請(qǐng)內(nèi)存空間用來(lái)存放, 而 strings.Builder 直接將底層的 []byte 利用指針的方式強(qiáng)轉(zhuǎn)為字符串.

//strings.Builder的String()
func (b *Builder) String() string {
    return *(*string)(unsafe.Pointer(&b.buf))
}

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

3.2 strings.Builder通常性能最優(yōu),但底層依賴于[]byte,所以如果平凡擴(kuò)容就不妙了,因此我們需要借助它的Grow方法,以已分配最終[]byte的容量,避免因?yàn)閿U(kuò)容帶來(lái)的性能損失

func Benchmark_StringConcat(b *testing.B) {
    str := "hello world"
    var sb strings.Builder
    sb.Grow(b.N * len(str))
    for i := 0; i < b.N; i++ {
        sb.WriteString(str)
    }
    _ = sb.String()
}

3.3 strings.Builder沒(méi)有拷貝構(gòu)造(借用C++說(shuō)法),因?yàn)?/p>

type Builder struct {  
addr *Builder // of receiver, to detect copies by value  
buf []byte  //如果拷貝,這個(gè)buf共享,最后導(dǎo)致數(shù)據(jù)混亂
}

到此,相信大家對(duì)“Golang中字符串拼接問(wèn)題怎么解決”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI