<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go1.18 快訊:字符串 Clone 有什么用?

          共 2678字,需瀏覽 6分鐘

           ·

          2021-11-19 09:43

          閱讀本文大概需要 6?分鐘。

          大家好,我是 polarisxu。

          Go 1.18 雖然還有 4 個月發(fā)布,但大部分的功能基本確定。我們可以提前知曉、熟悉。

          今天介紹的是標準庫中新增的一個 API:strings.Clone()

          從名稱可以知道,這是克隆。很多其他語言一開始就有這樣的功能。比如 PHP 有 clone 關(guān)鍵字、__clone 魔術(shù)方法;Java 的根類 Object 有 clone 方法等。

          01 函數(shù)簽名

          該函數(shù)的定義如下(見:https://pkg.go.dev/strings@master#Clone)

          //?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.
          //?For?strings?of?length?zero?the?string?""?will?be?returned
          //?and?no?allocation?is?made.
          func?Clone(s?string)?string

          Clone 返回 s 的新副本。它保證將 s 復制到一個新分配的副本中,當只保留一個很大的字符串中的一個小子字符串時,這一點很重要。使用克隆可以幫助這些程序使用更少的內(nèi)存。當然,由于使用克隆制作拷貝,過度使用克隆會使程序使用更多內(nèi)存。通常,只有在分析表明需要克隆時,才謹慎使用克隆。對于長度為零的字符串,將返回字符串 "",不進行內(nèi)存分配。

          02 舉例說明

          大家可能還是迷惑,不知道有啥用。舉一個代碼例子說明:

          package?main

          import?(
          ?"fmt"
          ?"reflect"
          ?"unsafe"
          )

          func?main()?{
          ?s?:=?"abcdefghijklmn"
          ?s1?:=?s[:4]

          ?sHeader?:=?(*reflect.StringHeader)(unsafe.Pointer(&s))
          ?s1Header?:=?(*reflect.StringHeader)(unsafe.Pointer(&s1))
          ?fmt.Println(sHeader.Len?==?s1Header.Len)
          ?fmt.Println(sHeader.Data?==?s1Header.Data)
          ??
          ??//?Output:
          ??//?false
          ??//?true
          }

          Len 不相等不需要解釋,Data 相等就值得注意。

          上面代碼,有些人可能不知道什么意思。這里涉及到 Go 中 string 類型的底層結(jié)構(gòu)。在 Go 中,string 類型的底層表示如下:

          type?string?struct?{
          ?ptr?unsafe.Pointer
          ?len?int
          }

          而 reflect.StringHeader 結(jié)構(gòu)是對字符串底層結(jié)構(gòu)的反射表示。

          在上面示例場景中,如果 s 很大,而之后我們只需要使用它的某個短子串,這會導致內(nèi)存的浪費,因為子串和原字符串的 Data 部分指向相同的內(nèi)存,因此整個字符串并不會被 GC 回收。

          strings.Clone 函數(shù)就是為了解決這個問題的:(要正常運行下面代碼,需要按照 Go tip 版本)

          s2?:=?strings.Clone(s[:4])

          s2Header?:=?(*reflect.StringHeader)(unsafe.Pointer(&s2))
          fmt.Println(sHeader.Len?==?s2Header.Len)
          fmt.Println(sHeader.Data?==?s2Header.Data)
          //?Output:
          //?false
          //?false

          通過克隆得到 s2,從最后輸出結(jié)果看,Data 已經(jīng)不同了,原始的長字符串就可以被垃圾回收了。(你也可以將傳遞給 Clone 的參數(shù)改為 s1,后面部分用 s1 和 s2 比)

          03 內(nèi)部實現(xiàn)

          知道了克隆的用途,再看看 strings.Clone 的實現(xiàn)。

          func?Clone(s?string)?string?{
          ?if?len(s)?==?0?{
          ??return?""
          ?}
          ?b?:=?make([]byte,?len(s))
          ?copy(b,?s)
          ?return?*(*string)(unsafe.Pointer(&b))
          }

          這里有兩個關(guān)鍵點:

          • 通過 copy 進行拷貝。其實普通的 slice,也會有需要克隆的場景,這時,需要我們手動執(zhí)行 copy 操作。
          • return 后面的語句 *(*string)(unsafe.Pointer(&b)),實現(xiàn) []byte 到 string 的零內(nèi)存拷貝轉(zhuǎn)換。

          04 總結(jié)

          Go 雖然有 GC,大部分時候不需要考慮內(nèi)存問題,但對內(nèi)存的使用,我們需要有敬畏之心,特別是大塊內(nèi)存、重復分配內(nèi)存的場景,我們需要知曉如何優(yōu)化,寫出真正高質(zhì)量的代碼。

          strings.Clone 的使用很簡單,但希望通過本文,你在寫 Go 代碼時,對類似場景下,slice 的正確使用有啟發(fā)(string 可以認為是特殊的 slice)。



          推薦閱讀


          福利

          我為大家整理了一份從入門到進階的Go學習資料禮包,包含學習建議:入門看什么,進階看什么。關(guān)注公眾號 「polarisxu」,回復?ebook?獲取;還可以回復「進群」,和數(shù)萬 Gopher 交流學習。

          瀏覽 58
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  香蕉性爱视频 | 国产黄色片在线免费观看 | 操逼逼视频 | 国产麻豆成人品免费观看 | 尤物视频最新网址 |