前言:
一如既往,繼續Go語言的學習,不過繼續學習之前,容許我再廢話幾句。最近發現堅持一件事情很重要,而且最近也發現堅持一件事情真的有點難。雖然文章基礎,不過我還是要堅持的,廢話完畢,那么就繼續吧。
一 Go語言之字符串
與大多數面向對象編程語言一樣,Go語言也具有string(字符串)類型,只不過它與其它語言例如java中的String類型不一樣的是它是值類型。並且注意聲明的關鍵字是string,全部小寫的哦,親(java程序員尤其注意,c#程序員偷樂中......)。除此之外,它還有個特性就是不可變性,這里需要注意的是指字符串本身不可變並不是字符串變量不可變,稍后看例子就能明白。在Go語言中string類型的結構如下:
1 struct String 2 { 3 byte* str; 4 int32 len; 5 };
上述結構可以在Go語言的源代碼中的runtime.h頭文件中找到。
從上述結構,我們可以看出,其實string類型是由一個byte指針和int32類型的表示字符串長度的變量兩部分組成。其中這里的byte是uint8的別名,實質上它就表示8位的無符號整數,因此本質上在計算機上字符串其實也就是數字而已。只不過,通過不同的編碼方式將數字映射到相應的字符上。而且在Go語言中使用的是UTF-8編碼方式。如果你還不明白所謂的編碼方式,那么請自己通過網絡查閱吧,因為涉及的知識點又會比較多,而今天我們只關注Go語言,所以這里就不細說了。
以上結構是Go語言的runtime中的c語言的結構體,所以,實際上在Go語言中的string類型你可以理解成內部就是上面的結構,至於是如何實現的,現在沒必要搞清楚,這關乎Go的語言底層實現了,暫時我們只需要使用就可以了。當然有興趣的也可以從底層去挖。
為了讓事情更好玩些,我們當然也可以在Go語言層面上模擬下上面的結構,當然實際中是毫無意義的,看下面:
在main函數中首先聲明定義了一個animal的字符串,然后將它轉成byte數組,並將它的地址傳給我們自定義的String結構體,但是String結構體的第一個參數不是一個指針類型嗎?沒錯,其實指針變量就是用來存放該類型的內存地址的變量,當它接收一個byte數組的首地址時,就可以控制數組了。所以,當我們傳遞給String結構體前面的那個b的byte數組的地址后,其實也就可以控制這個數組了。是不是已經暈了?嘿嘿,正常,當初剛學C語言的時候,筆者也一直沒明白指針。后來慢慢的就習慣了。再看上圖30行,這的print是我們自己定義的打印這個結構體的函數,當我們傳入String結構體類型cat變量后,第16行,我們循環遍歷結構體的指針變量,打印出它的每一個byte,由於Go語言不能和C語言一樣直接進行指針運算,所以需要引入unsafe包,通過它進行運算,這里就不詳細介紹了,如非需要了解可以查詢文檔,不過對於初學者來說沒什么大的意義,而且Go本來就不建議直接指針運算,不然直接用C好了,嘿嘿。通過上面的一頓折騰,最終將byte轉成string打印出來,所以最后byte數組又被還原成string了。
看完上面一段,估計有讀者要罵了,Go語言那么麻煩,比C語言還麻煩。請冷靜啊,上面的在實際開發中是幾乎很少用到的,不然還真不如直接用C語言了,我這里寫這一大堆,只是想闡釋下它的內部結構,順帶練習下Go的結構體,完全沒明白的也不用管,或許等隨着我們的深入學習,時間久了,再回來看就能明白了哦。
二 字符串操作
了解了字符串的基本情況后,我們再來看看對於字符串的操作。在上一節中,我們其實已經對字符串求了它的長度,就是通過len函數。不過它求得的結果並不是字符串中字符的個數,這似乎和其它一些的語言不太一樣,例如java。不過,當你賦值給它的都是英文字符的時候,似乎這個結果就是字符個數,但是當你將中文賦值給它后,就有些不太對了,不信可以試試。這里我將開發平台切換到了Linux,因為在windows下命令提示符下對於UTF-8的字符集操作不太方便。請看例子:
最終結果是:
結果是12,有圖有真相,為什么是這個結果呢?原因是在Go語言中,字符是utf-8編碼的,其中英文字符一個算一個字節,中文算三個字節。那么,我們如果非要得到字符個數呢?可以將string轉換成[]rune類型:
rune沒啥好奇怪的,其實就是int32的別名,所以這里其實是將string轉成了32位整數數組分別存入對應字符的unicode,這樣最終有幾個字符就對應幾個unicode分別位於數組中。因此最后可以得到長度為2。當然可以打印看下unicode是什么:
接下來,來點輕松的,大家都知道python中對數組可以切片,在Go中,也可以。如下:
最終結果:
今天就到這里,感覺文章越來越長了,額,沒辦法,隨着深入學習必然會這樣,但是我還是會盡量縮短每篇的長度的。希望對大家有幫助~