第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何(深度)在 Go 中復制字符串?

如何(深度)在 Go 中復制字符串?

Go
MMTTMM 2022-07-25 10:21:26
我可能應該先解釋一下為什么我想要那個。我理解 Go substring( s[i:j]) 和string.Split其他一些字符串操作就地工作:生成的子字符串共享原始字符串的相同內(nèi)存塊。例如,我讀取一個大字符串,解析并從中獲取一些子字符串,這些子字符串將長期保存在服務器程序中,它們將“持有”來自 GC 的大內(nèi)存塊,浪費內(nèi)存。我假設(shè)如果我可以復制這些子字符串并保留這些副本,GC 可以釋放那個大字符串。但是我在 Go 中找不到字符串復制機制,我嘗試再次將其轉(zhuǎn)換為[]bytethen string,在我的特定用例中內(nèi)存使用量下降了大約 3/4。但這感覺不對:第一,它引入了兩個復制操作。第二,由于我從未真正寫入該字節(jié)片,我懷疑它可能會在發(fā)布版本中得到優(yōu)化。我無法想象以前沒有人問過這個問題,但是我的搜索沒有產(chǎn)生任何相關(guān)的結(jié)果,或者在 Go 中有一些更好的做法來做這些事情嗎?順便說一句,我嘗試向+""它附加一個空字符串(),內(nèi)存消耗并沒有下降,我認為即使在測試版本中它也得到了優(yōu)化。為了測量內(nèi)存使用情況,我調(diào)用runtime.GC()thenruntime.ReadMemStats()和 compare MemStats.Alloc,這在我的測試中似乎非常一致。
查看完整描述

4 回答

?
天涯盡頭無女友

TA貢獻1831條經(jīng)驗 獲得超9個贊

Go 中的字符串一旦創(chuàng)建就不可變。去規(guī)范


我會更喜歡下面的builder。您繼續(xù)添加到構(gòu)建器的緩沖區(qū)(可變)WriteString 并且一旦完成調(diào)用String返回指針而不是緩沖區(qū)切片的另一個副本的方法。


    somestring := "Hello Go"

    var sb strings.Builder

    if _, err := sb.WriteString(somestring); err != nil {

        //log & return

    }

    newstring := sb.String()

從 go 源碼檢查 builder 的 String() 的實現(xiàn)。它返回指針并轉(zhuǎn)換為 *string。沒有第二份。


// String returns the accumulated string.

func (b *Builder) String() string {

    return *(*string)(unsafe.Pointer(&b.buf))

}


查看完整回答
反對 回復 2022-07-25
?
慕田峪7331174

TA貢獻1828條經(jīng)驗 獲得超13個贊

另一種選擇是,從 go 1.18(2021 年第四季度)開始:

sCopy := strings.Clone(s)

它來自問題4020045038,并從 CL(更改列表)334884345849 開始

字節(jié),字符串:添加克隆

直接使用[]byte并且string很常見并且需要經(jīng)常復制它們。
此更改Clone為字符串和字節(jié)添加了一個助手來滿足此需求。
還添加了一個基準,以提供證據(jù)說明為什么bytes.Clone使用copy.

字符串:添加克隆功能

strings.Clone函數(shù)復制輸入字符串,但返回的克隆字符串不引用輸入字符串內(nèi)存

strings/clone.go

// Clone returns a fresh copy of s.

//

// It guarantees to make a copy of s into a new allocation,

// which can be important when retaining only a small substring

// of a much larger string. Using Clone can help such programs

// use less memory. 

//

// Of course, since using Clone makes a copy,

// overuse of Clone can make programs use more memory.

//

// Clone should typically be used only rarely, and only when

// profiling indicates that it is needed.

//

func Clone(s string) string {

    b := make([]byte, len(s))

    copy(b, s)

    return *(*string)(unsafe.Pointer(&b))

}


查看完整回答
反對 回復 2022-07-25
?
紅顏莎娜

TA貢獻1842條經(jīng)驗 獲得超13個贊

字符串被實現(xiàn)為指向底層字節(jié)數(shù)組和字符串長度的指針。當您從現(xiàn)有字符串創(chuàng)建切片時,新字符串仍指向基礎(chǔ)數(shù)組,可能指向該數(shù)組中具有不同長度的不同偏移量。這樣,許多小字符串可以使用單個底層大數(shù)組。

正如您所指出的,如果您有一個大字符串并將其解析為較小的字符串,那么您最終會將大字符串保留在內(nèi)存中,因為 GC 只知道底層數(shù)組和指向它的指針。有兩種方法可以處理這個問題:

  • 不要使用大字符串,而是保留[]byte或使用基于字節(jié)流的讀取器/掃描器,并在解析時從輸入創(chuàng)建字符串。這樣 GC 將[]byte在解析完成時收集底層,并且您將擁有沒有底層大塊的字符串。

  • 執(zhí)行您已經(jīng)描述的操作,并使用string([]byte(s[x:y]))或使用copy.


查看完整回答
反對 回復 2022-07-25
?
慕無忌1623718

TA貢獻1744條經(jīng)驗 獲得超4個贊

使用以下函數(shù)深度復制字符串:


func deepCopy(s string) string {

    b := make([]byte, len(s))

    copy(b, s)

    return *(*string)(unsafe.Pointer(&b))

}

該函數(shù)將數(shù)據(jù)復制到新分配的字節(jié)片中。該函數(shù)使用 unsafe 包將切片標頭轉(zhuǎn)換為不復制字節(jié)的字符串標頭。


如果直接使用 unsafe 包是一個問題,那么使用strings.Builder。strings.Builder 類型在幕后執(zhí)行不安全的惡作劇。


 func deepCopy(s string) string {

     var sb strings.Builder

     sb.WriteString(s)

     return sb.String()

 }

無需檢查 sb.WriteString 返回的錯誤。Builder.WriteString方法有錯誤返回,所以 Builder 類型滿足 io.StringWriter接口,而不是因為 WriteString 可以返回非 nil 錯誤。


查看完整回答
反對 回復 2022-07-25
  • 4 回答
  • 0 關(guān)注
  • 189 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號