基本數(shù)據(jù)類型
Go 原生支持的數(shù)值類型有哪些?
- Go 語言的類型大體可分為基本數(shù)據(jù)類型、復(fù)合數(shù)據(jù)類型和接口類型這三種。
- 其中,我們?nèi)粘?Go 編碼中使用最多的就是基本數(shù)據(jù)類型,而基本數(shù)據(jù)類型中使用占比最大的又是數(shù)值類型。
整型
- Go 語言的整型,主要用來表示現(xiàn)實(shí)世界中整型數(shù)量等。它可以分為平臺(tái)無關(guān)整型和平臺(tái)相關(guān)整型這兩種,它們的區(qū)別主要就在,這些整數(shù)類型在不同 CPU 架構(gòu)或操作系統(tǒng)下面,它們的長度是否是一致的。
- 平臺(tái)無關(guān)整型
- 它們?cè)谌魏?CPU 架構(gòu)或任何操作系統(tǒng)下面,長度都是固定不變的。
- 有符號(hào)整型(int8-int64)和無符號(hào)整型(uint8-uint64)的本質(zhì)差別在于最高二進(jìn)制位(bit 位)是否被解釋為符號(hào)位,這點(diǎn)會(huì)影響到無符號(hào)整型與有符號(hào)整型的取值范圍。
- Go 采用 2 的補(bǔ)碼(Two’s Complement)作為整型的比特位編碼方法。因此,我們不能簡單地將最高比特位看成負(fù)號(hào),把其余比特位表示的值看成負(fù)號(hào)后面的數(shù)值。Go 的補(bǔ)碼是通過原碼逐位取反后再加 1 得到的。
- 它們?cè)谌魏?CPU 架構(gòu)或任何操作系統(tǒng)下面,長度都是固定不變的。
- 平臺(tái)相關(guān)整型
- 與平臺(tái)無關(guān)整型對(duì)應(yīng)的就是平臺(tái)相關(guān)整型,它們的長度會(huì)根據(jù)運(yùn)行平臺(tái)的改變而改變。
- Go 語言原生提供了三個(gè)平臺(tái)相關(guān)整型,它們是 int、uint 與 uintptr。
- 由于這三個(gè)類型的長度是平臺(tái)相關(guān)的,所以我們?cè)诰帉懹幸浦残砸蟮拇a時(shí),千萬不要強(qiáng)依賴這些類型的長度。
- 如果不知道這三個(gè)類型在目標(biāo)運(yùn)行平臺(tái)上的長度,可以通過 unsafe 包提供的 SizeOf 函數(shù)來獲取。
- 平臺(tái)無關(guān)整型
- 整型的溢出問題
- 如果這個(gè)整型因?yàn)閰⑴c某個(gè)運(yùn)算,導(dǎo)致結(jié)果超出了這個(gè)整型的值邊界,我們就說發(fā)生了整型溢出的問題。
- 由于整型無法表示它溢出后的那個(gè)“結(jié)果”,所以出現(xiàn)溢出情況后,對(duì)應(yīng)的整型變量的值依然會(huì)落到它的取值范圍內(nèi),只是結(jié)果值與我們的預(yù)期不符,導(dǎo)致程序邏輯出錯(cuò)。
- 字面值與格式化輸出
- Go 語言在設(shè)計(jì)開始,就繼承了 C 語言關(guān)于數(shù)值字面值(Number Literal)的語法形式。
- 早期 Go 版本支持十進(jìn)制、八進(jìn)制、十六進(jìn)制的數(shù)值字面值形式。
- Go 1.13 版本中,Go 又增加了對(duì)二進(jìn)制字面值的支持和兩種八進(jìn)制字面值的形式。
- 為提升字面值的可讀性,Go 1.13 版本還支持在字面值中增加數(shù)字分隔符“_”,分隔符可以用來將數(shù)字分組以提高可讀性。
- 反過來,我們也可以通過標(biāo)準(zhǔn)庫 fmt 包的格式化輸出函數(shù),將一個(gè)整型變量輸出為不同進(jìn)制的形式。
浮點(diǎn)型
- 浮點(diǎn)型的二進(jìn)制表示
-
Go 語言提供了 float32 與 float64 兩種浮點(diǎn)類型,它們分別對(duì)應(yīng)單精度與雙精度浮點(diǎn)數(shù)值類型。
- 不過,Go 語言中沒有提供 float 類型。
- 換句話說,Go 提供的浮點(diǎn)類型都是平臺(tái)無關(guān)的。
- 無論是 float32 還是 float64,它們的變量的默認(rèn)值都為 0.0,不同的是它們占用的內(nèi)存空間大小是不一樣的,可以表示的浮點(diǎn)數(shù)的范圍與精度也不同。
- 浮點(diǎn)數(shù)在內(nèi)存中的二進(jìn)制表示(Bit Representation)要比整型復(fù)雜得多:
- 浮點(diǎn)數(shù)在內(nèi)存中的二進(jìn)制表示分三個(gè)部分:符號(hào)位、階碼(即經(jīng)過換算的指數(shù)),以及尾數(shù)。這樣表示的一個(gè)浮點(diǎn)數(shù),它的值等于:
(
?
1
)
s
?
1.
M
?
2
E
?
o
f
f
s
e
t
(-1)^s * 1.M * 2 ^{E-offset}
(?1)s?1.M?2E?offset。
- 當(dāng)符號(hào)位為 1 時(shí),浮點(diǎn)值為負(fù)值;
- 當(dāng)符號(hào)位為 0 時(shí),浮點(diǎn)值為正值。
- 公式中 offset 被稱為階碼偏移值。
- 單精度(float32)與雙精度(float64)浮點(diǎn)數(shù)在階碼和尾數(shù)上的不同:
- 單精度浮點(diǎn)類型(float32)為符號(hào)位分配了 1 個(gè) bit,為階碼分配了 8 個(gè) bit,剩下的 23 個(gè) bit 分給了尾數(shù)。
- 而雙精度浮點(diǎn)類型,除了符號(hào)位的長度與單精度一樣之外,其余兩個(gè)部分的長度都要遠(yuǎn)大于單精度浮點(diǎn)型,階碼可用的 bit 位數(shù)量為 11,尾數(shù)則更是擁有了 52 個(gè) bit 位。
- 浮點(diǎn)數(shù)在內(nèi)存中的二進(jìn)制表示分三個(gè)部分:符號(hào)位、階碼(即經(jīng)過換算的指數(shù)),以及尾數(shù)。這樣表示的一個(gè)浮點(diǎn)數(shù),它的值等于:
(
?
1
)
s
?
1.
M
?
2
E
?
o
f
f
s
e
t
(-1)^s * 1.M * 2 ^{E-offset}
(?1)s?1.M?2E?offset。
-
Go 語言提供了 float32 與 float64 兩種浮點(diǎn)類型,它們分別對(duì)應(yīng)單精度與雙精度浮點(diǎn)數(shù)值類型。
- 字面值與格式化輸出
- Go 浮點(diǎn)類型字面值大體可分為兩類,一類是直白地用十進(jìn)制表示的浮點(diǎn)值形式。這一類,我們通過字面值就可直接確定它的浮點(diǎn)值。
- 另一類則是科學(xué)計(jì)數(shù)法形式。采用科學(xué)計(jì)數(shù)法表示的浮點(diǎn)字面值,我們需要通過一定的換算才能確定其浮點(diǎn)值。而且在這里,科學(xué)計(jì)數(shù)法形式又分為十進(jìn)制形式表示的,和十六進(jìn)制形式表示的兩種。
6674.28e-2 // 6674.28 * 10^(-2) = 66.742800 .12345E+5 // 0.12345 * 10^5 = 12345.000000 0x2.p10 // 2.0 * 2^10 = 2048.000000 0x1.Fp+0 // 1.9375 * 2^0 = 1.937500
復(fù)數(shù)類型
- Go 提供兩種復(fù)數(shù)類型,它們分別是 complex64 和 complex128,complex64 的實(shí)部與虛部都是 float32 類型,而 complex128 的實(shí)部與虛部都是 float64 類型。如果一個(gè)復(fù)數(shù)沒有顯示賦予類型,那么它的默認(rèn)類型為 complex128。
- 關(guān)于復(fù)數(shù)字面值的表示,我們其實(shí)有三種方法:
- 第一種,我們可以通過復(fù)數(shù)字面值直接初始化一個(gè)復(fù)數(shù)類型變量:
var c = 5 + 6i
。 - 第二種,Go 還提供了 complex 函數(shù),方便我們創(chuàng)建一個(gè) complex128 類型值:
var c = complex(5, 6) // 5 + 6i
。 - 第三種,你還可以通過 Go 提供的預(yù)定義的函數(shù) real 和 imag,來獲取一個(gè)復(fù)數(shù)的實(shí)部與虛部,返回值為一個(gè)浮點(diǎn)類型:
var c = complex(5, 6) // 5 + 6i r := real(c) // 5.000000 i := imag(c) // 6.000000
- 第一種,我們可以通過復(fù)數(shù)字面值直接初始化一個(gè)復(fù)數(shù)類型變量:
字符串類型
- 在 Go 中,字符串類型為 string。
- Go 語言通過 string 類型統(tǒng)一了對(duì)“字符串”的抽象。
- 這樣無論是字符串常量、字符串變量或是代碼中出現(xiàn)的字符串字面值,它們的類型都被統(tǒng)一設(shè)置為 string。
- string 類型的數(shù)據(jù)是不可變的,提高了字符串的并發(fā)安全性和存儲(chǔ)利用率。
- Go 字符串的組成
- Go 語言中的字符串值也是一個(gè)可空的字節(jié)序列,字節(jié)序列中的字節(jié)個(gè)數(shù)稱為該字符串的長度。一個(gè)個(gè)的字節(jié)只是孤立數(shù)據(jù),不表意。
- 字符串是由一個(gè)可空的字符序列構(gòu)成。
- rune 類型與字符字面值
- Go 使用 rune 這個(gè)類型來表示一個(gè) Unicode 碼點(diǎn)。rune 本質(zhì)上是 int32 類型的別名類型,它與 int32 類型是完全等價(jià)的。
- 一個(gè) rune 實(shí)例就是一個(gè) Unicode 字符,一個(gè) Go 字符串也可以被視為 rune 實(shí)例的集合。我們可以通過字符字面值來初始化一個(gè) rune 變量。
- 在 Go 中,字符字面值有多種表示法,最常見的是通過單引號(hào)括起的字符字面值。
- 我們還可以使用 Unicode 專用的轉(zhuǎn)義字符\u 或\U 作為前綴,來表示一個(gè) Unicode 字符。
- 由于表示碼點(diǎn)的 rune 本質(zhì)上就是一個(gè)整型數(shù),所以我們還可用整型值來直接作為字符字面值給 rune 變量賦值。
- 字符串字面值
- 字符串是字符的集合,我們需要把表示單個(gè)字符的單引號(hào),換為表示多個(gè)字符組成的字符串的雙引號(hào)。
- string 類型其實(shí)是一個(gè)“描述符”,它本身并不真正存儲(chǔ)字符串?dāng)?shù)據(jù),而僅是由一個(gè)指向底層存儲(chǔ)的指針和字符串的長度字段組成的。
- 我們直接將 string 類型通過函數(shù) / 方法參數(shù)傳入也不會(huì)帶來太多的開銷。因?yàn)閭魅氲膬H僅是一個(gè)“描述符”,而不是真正的字符串?dāng)?shù)據(jù)。
- Go 字符串類型的常見操作
- 下標(biāo)
- 在字符串的實(shí)現(xiàn)中,真正存儲(chǔ)數(shù)據(jù)的是底層的數(shù)組。
- 字符串的下標(biāo)操作本質(zhì)上等價(jià)于底層數(shù)組的下標(biāo)操作。
var s = "中國人" fmt.Printf("0x%x\n", s[0]) // 0xe4:字符“中” utf-8編碼的第一個(gè)字節(jié)
- 通過下標(biāo)操作,我們獲取的是字符串中特定下標(biāo)上的字節(jié),而不是字符。
- 字符迭代
- Go 有兩種迭代形式:常規(guī) for 迭代與 for range 迭代。
- 通過這兩種形式的迭代對(duì)字符串進(jìn)行操作得到的結(jié)果是不同的。
- 通過常規(guī) for 迭代對(duì)字符串進(jìn)行的操作是一種字節(jié)視角的迭代,每輪迭代得到的的結(jié)果都是組成字符串內(nèi)容的一個(gè)字節(jié),以及該字節(jié)所在的下標(biāo)值,這也等價(jià)于對(duì)字符串底層數(shù)組的迭代。
- 通過 for range 迭代,我們每輪迭代得到的是字符串中 Unicode 字符的碼點(diǎn)值,以及該字符在字符串中的偏移值。
- 我們可以通過這樣的迭代,獲取字符串中的字符個(gè)數(shù),而通過 Go 提供的內(nèi)置函數(shù) len,我們只能獲取字符串內(nèi)容的長度(字節(jié)個(gè)數(shù))。
- 獲取字符串中字符個(gè)數(shù)更專業(yè)的方法,是調(diào)用標(biāo)準(zhǔn)庫 UTF-8 包中的 RuneCountInString 函數(shù)。
- 字符串連接
- Go 原生支持通過 +/+= 操作符進(jìn)行字符串連接。
- 雖然通過 +/+= 進(jìn)行字符串連接的開發(fā)體驗(yàn)是最好的,但連接性能就未必是最快的了。
- 除了這個(gè)方法外,Go 還提供了 strings.Builder、strings.Join、fmt.Sprintf 等函數(shù)來進(jìn)行字符串連接操作。
- 字符串比較
- Go 字符串類型支持各種比較關(guān)系操作符,包括 = =、!= 、>=、<=、> 和 <。
-
在字符串的比較上,Go 采用字典序的比較策略,分別從每個(gè)字符串的起始處,開始逐個(gè)字節(jié)地對(duì)兩個(gè)字符串類型變量進(jìn)行比較。
- 當(dāng)兩個(gè)字符串之間出現(xiàn)了第一個(gè)不相同的元素,比較就結(jié)束了,這兩個(gè)元素的比較結(jié)果就會(huì)做為串最終的比較結(jié)果。
- 如果出現(xiàn)兩個(gè)字符串長度不同的情況,長度比較小的字符串會(huì)用空元素補(bǔ)齊,空元素比其他非空元素都小。
- 鑒于 Go string 類型是不可變的,所以說如果兩個(gè)字符串的長度不相同,那么我們不需要比較具體字符串?dāng)?shù)據(jù),也可以斷定兩個(gè)字符串是不同的。但是如果兩個(gè)字符串長度相同,就要進(jìn)一步判斷,數(shù)據(jù)指針是否指向同一塊底層存儲(chǔ)數(shù)據(jù)。如果還相同,那么我們可以說兩個(gè)字符串是等價(jià)的,如果不同,那就還需要進(jìn)一步去比對(duì)實(shí)際的數(shù)據(jù)內(nèi)容。
- 字符串轉(zhuǎn)換
- Go 支持字符串與字節(jié)切片、字符串與 rune 切片的雙向轉(zhuǎn)換,并且這種轉(zhuǎn)換無需調(diào)用任何函數(shù),只需使用顯式類型轉(zhuǎn)換就可以了。
- 下標(biāo)
文章來源地址http://www.zghlxwxcb.cn/news/detail-659249.html
文章來源:http://www.zghlxwxcb.cn/news/detail-659249.html
到了這里,關(guān)于《Go 語言第一課》課程學(xué)習(xí)筆記(八)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!