<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### 內置定義 Go標準庫builtin給出了所有內置類型的定義。 源代碼位于src/builtin/builtin.go,其中關于string的描述如下: ~~~ // string is the set of all strings of 8-bit bytes, conventionally but not // necessarily representing UTF-8-encoded text. A string may be empty, but // not nil. Values of string type are immutable. type string string ~~~ 所以string是8比特字節的集合,通常是但并不一定非得是UTF-8編碼的文本。 另外,還提到了兩點,非常重要: * string可以為空(長度為0),但不會是nil; * string對象不可以修改; ### string 數據結構 源碼包`src/runtime/string.go:stringStruct`定義了string的數據結構: ~~~go type stringStruct struct { str unsafe.Pointer len int } ~~~ 其數據結構很簡單: * stringStruct.str:字符串的首地址; * stringStruct.len:字符串的長度; ### string構建 如下代碼所示,可以聲明一個string變量變賦予初值: ~~~go var str string str = "Hello World" ~~~ 字符串構建過程是先根據字符串構建stringStruct,再轉換成string。轉換的源碼如下: ~~~go func gostringnocopy(str *byte) string { // 根據字符串地址構建string ss := stringStruct{str: unsafe.Pointer(str), len: findnull(str)} // 先構造stringStruct s := *(*string)(unsafe.Pointer(&ss)) // 再將stringStruct轉換成string return s } ~~~ string在runtime包中就是stringStruct,對外呈現叫做string ### []byte轉string byte切片可以很方便的轉換成string,如下所示: ~~~go func GetStringBySlice(s []byte) string { return string(s) } ~~~ 需要注意的是這種轉換需要一次內存拷貝。 轉換過程如下: 1. 根據切片的長度申請內存空間,假設內存地址為p,切片長度為len(b); 2. 構建string(string.str = p;string.len = len;) 3. 拷貝數據(切片中數據拷貝到新申請的內存空間) 轉換示意圖: ![](https://img.kancloud.cn/9d/87/9d8724872269e7ec8e7cd708b1556a6b_542x366.png) ### string轉[]byte string也可以方便的轉成byte切片,如下所示: ~~~go func GetSliceByString(str string) []byte { return []byte(str) } ~~~ string轉換成byte切片,也需要一次內存拷貝,其過程如下: * 申請切片內存空間 * 將string拷貝到切片 轉換示意圖: ![](https://img.kancloud.cn/34/15/34154daf22954b5cc7338fa3a26f579d_542x366.png) ### 字符串拼接 字符串可以很方便的拼接,像下面這樣: ~~~go str := "Str1" + "Str2" + "Str3" ~~~ 即便有非常多的字符串需要拼接,性能上也有比較好的保證,因為新字符串的內存空間是一次分配完成的,所以性能消耗主要在拷貝數據上。 一個拼接語句的字符串編譯時都會被存放到一個切片中,拼接過程需要遍歷兩次切片,第一次遍歷獲取總的字符串長度,據此申請內存,第二次遍歷會把字符串逐個拷貝過去。 字符串拼接偽代碼如下: ~~~go func concatstrings(a []string) string { // 字符串拼接 length := 0 // 拼接后總的字符串長度 for _, str := range a { length += len(str) } s, b := rawstring(length) // 生成指定大小的字符串,返回一個string和切片,二者共享內存空間 for _, str := range a { copy(b, str) // string無法修改,只能通過切片修改 b = b[len(str):] } return s } ~~~ 因為string是無法直接修改的,所以這里使用rawstring()方法初始化一個指定大小的string,同時返回一個切片,二者共享同一塊內存空間,后面向切片中拷貝數據,也就間接修改了string。 rawstring()源代碼如下: ~~~go func rawstring(size int) (s string, b []byte) { // 生成一個新的string,返回的string和切片共享相同的空間 p := mallocgc(uintptr(size), nil, false) stringStructOf(&s).str = p stringStructOf(&s).len = size *(*slice)(unsafe.Pointer(&b)) = slice{p, size, size} return } ~~~ ## 為什么字符串不允許修改? 像C++語言中的string,其本身擁有內存空間,修改string是支持的。但Go的實現中,string不包含內存空間,只有一個內存的指針,這樣做的好處是string變得非常輕量,可以很方便的進行傳遞而不用擔心內存拷貝。 因為string通常指向字符串字面量,而字符串字面量存儲位置是只讀段,而不是堆或棧上,所以才有了string不可修改的約定。 ## []byte轉換成string一定會拷貝內存嗎? byte切片轉換成string的場景很多,為了性能上的考慮,有時候只是臨時需要字符串的場景下,byte切片轉換成string時并不會拷貝內存,而是直接返回一個string,這個string的指針(string.str)指向切片的內存。 比如,編譯器會識別如下臨時場景: * 使用m\[string(b)\]來查找map(map是string為key,臨時把切片b轉成string); * 字符串拼接,如””; * 字符串比較:string(b) == “foo” 因為是臨時把byte切片轉換成string,也就避免了因byte切片同容改成而導致string引用失敗的情況,所以此時可以不必拷貝內存新建一個string。 ## string和\[\]byte如何取舍 string和\[\]byte都可以表示字符串,但因數據結構不同,其衍生出來的方法也不同,要根據實際應用場景來選擇。 string 擅長的場景: * 需要字符串比較的場景; * 不需要nil字符串的場景; \[\]byte擅長的場景: * 修改字符串的場景,尤其是修改粒度為1個字節; * 函數返回值,需要用nil表示含義的場景; * 需要切片操作的場景; 雖然看起來string適用的場景不如\[\]byte多,但因為string直觀,在實際應用中還是大量存在,在偏底層的實現中\[\]byte使用更多
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看