柚子快報(bào)邀請(qǐng)碼778899分享:Golang學(xué)習(xí)-基本數(shù)據(jù)類(lèi)型
柚子快報(bào)邀請(qǐng)碼778899分享:Golang學(xué)習(xí)-基本數(shù)據(jù)類(lèi)型
整型
Go語(yǔ)言同時(shí)提供了有符號(hào)和無(wú)符號(hào)類(lèi)型的整數(shù)運(yùn)算。這里有int8、int16、int32、int64四種大小不同的有符號(hào)整數(shù)類(lèi)型,分別對(duì)應(yīng)8、16、32、64bit大小的有符號(hào)整數(shù),與此對(duì)應(yīng)的是uint8、uint16、uint32、uint64四種大小不同的無(wú)符號(hào)整數(shù)類(lèi)型。
這里還有兩種一般對(duì)應(yīng)特定CPU平臺(tái)機(jī)器字大小的有符號(hào)和無(wú)符號(hào)整數(shù)int和uint;其中int是應(yīng)用最廣泛的數(shù)值類(lèi)型。這兩種類(lèi)型都有同樣的大小,32或者64bit,但是我們不能對(duì)此做任何的假設(shè);因?yàn)椴煌幾g器即使在相同的硬件平臺(tái)上可能產(chǎn)生不同的大小。
最后,還有一種無(wú)符號(hào)的整數(shù)類(lèi)型uintptr,沒(méi)有指定具體的bit大小但是足以容納指針。uintpir類(lèi)型只有在底層編程時(shí)才需要,特別是Go語(yǔ)言和C語(yǔ)言函數(shù)庫(kù)或者操作系統(tǒng)接口相互的地方。我們將在后面的unsafe包相關(guān)部分看到類(lèi)似的例子。
一個(gè)算數(shù)運(yùn)算的結(jié)果,不論是有符號(hào)的還是無(wú)符號(hào)的,如果需要更多的bit位才能正確表示的話(huà),就說(shuō)明了計(jì)算結(jié)果是溢出了。超出的高位的bit位部分將被丟棄。如果原始的數(shù)值是有符號(hào)類(lèi)型,而且最左邊的bit位是1的話(huà),那么最終結(jié)果可能是負(fù)的,例如int8的例子:
var u uint8 = 255
fmt.Println(u, u+1, u*u) // "255 0 1"
var i int8 = 127
fmt.Println(i, i+1, i*i) // "127 -128 1"
相同的整數(shù)類(lèi)型可以使用比較運(yùn)算符進(jìn)行比較,事實(shí)上,布爾型,數(shù)字類(lèi)型和字符串類(lèi)型等基本數(shù)據(jù)類(lèi)型都是可以比較的。
var x uint16 = 122
var y uint16 = 360
fmt.Println(x > y) //false
var z uint8 = 109
fmt.Println(x > (uint16(z))) //true
在上面的案例中 x和y都是uint16類(lèi)型,可以直接比較, z是uint8類(lèi)型,不能直接和x比較,需要轉(zhuǎn)換為uint16類(lèi)型才能比較。此處需要注意的是,許多整數(shù)之間的互相轉(zhuǎn)換并不會(huì)改變數(shù)值,它們只是告訴編譯器如何解釋這個(gè)值。但是對(duì)于將一個(gè)大尺寸的整數(shù)類(lèi)型轉(zhuǎn)換為一個(gè)小尺寸類(lèi)型的整數(shù)類(lèi)型,或者是將一個(gè)浮點(diǎn)數(shù)轉(zhuǎn)換為整數(shù)時(shí),可能會(huì)改變數(shù)值或者丟失精度。
var h uint16 = 360
fmt.Println(uint8(h)) //104
浮點(diǎn)數(shù)
Go提供了兩種精度的浮點(diǎn)數(shù),float32和float64。這些浮點(diǎn)數(shù)類(lèi)型的取值可以從很微小到很巨大。浮點(diǎn)數(shù)的范圍極限值可以在math包找到。 一個(gè)float32類(lèi)型的浮點(diǎn)數(shù)可以提供大約6個(gè)十進(jìn)制數(shù)的精度,而float64則可以提供約15個(gè)十進(jìn)制數(shù)的精度;通常應(yīng)該優(yōu)先使用float64類(lèi)型,因?yàn)閒loat32類(lèi)型的累計(jì)計(jì)算誤差很容易擴(kuò)散,并且float32能精確表示的正整數(shù)并不是很大(因?yàn)閒loat32的有效bit位只有23個(gè),其它的bit位用于指數(shù)和符號(hào);當(dāng)整數(shù)大于23bit能表達(dá)的范圍時(shí),float32的表示將出現(xiàn)誤差):
var float32Max float32 = math.MaxFloat32
fmt.Println(float32Max) //3.4028235e+38
var float64Max float64 = math.MaxFloat64
fmt.Println(float64Max) //1.7976931348623157e+308
var f float32 = 1 << 24
fmt.Println(f) //1.6777216e+07
fmt.Println(f == f+1) //true
布爾類(lèi)型
一個(gè)布爾類(lèi)型的值只有兩種:true和false。if和for語(yǔ)句的條件部分都是布爾類(lèi)型的值,并且==和<等比較操作也會(huì)產(chǎn)生布爾型的值。一元操作符!對(duì)應(yīng)邏輯非操作,因此!true的值為false,更羅嗦的說(shuō)法是(!true==false)==true,雖然表達(dá)方式不一樣,不過(guò)我們一般會(huì)采用簡(jiǎn)潔的布爾表達(dá)式,就像用x來(lái)表示x==true。
布爾值可以和&&(AND)和||(OR)操作符結(jié)合,并且有短路行為:如果運(yùn)算符左邊值已經(jīng)可以確定整個(gè)布爾表達(dá)式的值,那么運(yùn)算符右邊的值將不再被求值,因此下面的表達(dá)式總是安全的:
var s string
tag := s != "" && s[0] == 'x'
fmt.Println(tag)
字符串
一個(gè)字符串是一個(gè)不可改變的字節(jié)序列。字符串可以包含任意的數(shù)據(jù),包括byte值0,但是通常是用來(lái)包含人類(lèi)可讀的文本,文本字符通常被解釋為采用UTF-8編碼的Unicode碼點(diǎn)(rune)序列。
內(nèi)置的len函數(shù)可以返回一個(gè)字符中的字節(jié)數(shù)目,索引操作返回的該字節(jié)的值。
s := "hello,world中文"
fmt.Println(len(s)) //17
fmt.Println(s[0], s[9]) //104 108
如上圖所示,len() 函數(shù)返回的并不是對(duì)應(yīng)的字符數(shù),而是該字符串對(duì)應(yīng)的字節(jié)數(shù)目(一個(gè)字符對(duì)應(yīng)一個(gè)或者多個(gè)字節(jié)),索引返回的也是字節(jié)值。
字符串操作 s[i:j] 基于s字符串的第i個(gè)字節(jié)到第j(并不包含j本身)個(gè)字節(jié)生成一個(gè)新的字符串。生成的新字符串將包含j-i個(gè)字節(jié)
fmt.Println(s[0:5]) //hello
還是需要注意此處雖然返回了完整的 hello,也就是[0:5]的字符,但是是因?yàn)檫@些字符編碼的時(shí)候都只使用了一個(gè)字節(jié),所以才會(huì)出現(xiàn)這樣的情況。
字符串可以用==和<進(jìn)行比較;比較通過(guò)逐個(gè)字節(jié)比較完成的,因此比較的結(jié)果是字符串自然編碼的結(jié)果。
字符串的值是不可變的:一個(gè)字符串包含的字節(jié)序列永遠(yuǎn)不會(huì)被改變,當(dāng)然我們也可以給一個(gè)字符串變量分配一個(gè)新的字符串值。如下
z := "left foot"
t := z
z += ",right foot"
fmt.Println(t) // left foot
fmt.Println(z) // left foot,right foot
因?yàn)樽址遣豢尚薷牡模虼艘膊豢梢酝ㄟ^(guò)修改字符串對(duì)應(yīng)的字節(jié)數(shù)據(jù)
s[0] = 'L' // compile error: cannot assign to s[0]
字符串和Byte切片
標(biāo)準(zhǔn)庫(kù)種有四個(gè)包隊(duì)字符串的處理尤為重要:bytes、strings、strconv、unicode包。strings包提供了許多如字符串的查詢(xún)、替換、比較、截?cái)唷⒉鸱趾秃喜⒌裙δ堋?/p>
bytes包也提供了跟多類(lèi)似功能的函數(shù),但是針對(duì)和字符串相同結(jié)構(gòu)的[]byte類(lèi)型。因?yàn)樽址侵蛔x的,因此逐步構(gòu)建字符串會(huì)導(dǎo)致很多分配和復(fù)制。在這種情況下,使用bytes.Buffer類(lèi)型將會(huì)更有效,稍后我們將展示。
strconv包提供了布爾型、整數(shù)型、浮點(diǎn)數(shù)和對(duì)應(yīng)字符串的相互轉(zhuǎn)換,還提供了雙引號(hào)轉(zhuǎn)義相關(guān)的轉(zhuǎn)換。
unicode包提供了IsDigit、IsLetter、IsUpper和IsLower等類(lèi)似功能,它們用于給字符分類(lèi)。每個(gè)函數(shù)有一個(gè)單一的rune類(lèi)型的參數(shù),然后返回一個(gè)布爾值。而像Toupper和ToLower之類(lèi)的轉(zhuǎn)換函數(shù)用于rune字符的大小寫(xiě)轉(zhuǎn)換。所有的這些函數(shù)都是遵循Unicode標(biāo)準(zhǔn)定義的字母、數(shù)字等分類(lèi)規(guī)范。strings包也有類(lèi)似的函數(shù),它們是ToUpper和ToLower,將原始字符串的每個(gè)字符都做相應(yīng)的轉(zhuǎn)換,然后返回新的字符串。
其中幾個(gè)簡(jiǎn)單的的示例
func main() {
fmt.Println(basename("usr/local/temp/a.bin")) // a
fmt.Println(toInt("1234", 10)) // 123456
fmt.Println(toInt("f564", 16)) // 62820
}
func basename(s string) string {
slash := strings.LastIndex(s, "/") //-1 if "/" not found
s = s[slash+1:]
if dot := strings.LastIndex(s, "."); dot >= 0 {
s = s[:dot]
}
return s
}
func toInt(s string, base int) int64 {
result, e := strconv.ParseInt(s, base, 64)
if e != nil {
fmt.Println(e.Error())
}
return result
}
常量
常量表達(dá)式的值在編譯期計(jì)算,而不是在運(yùn)行期。每種常量的潛在類(lèi)型都是基礎(chǔ)類(lèi)型:boolean,string或數(shù)字。 一個(gè)常量的聲明語(yǔ)句定義了常量的名字,和變量的聲明語(yǔ)法類(lèi)型,常量的值不可修改,這樣可以防止在運(yùn)行期被意外或惡意的修改。例如,常量比變量更適合表達(dá)π之類(lèi)的數(shù)字常數(shù),因?yàn)樗麄兊闹挡粫?huì)發(fā)生變化:
const pi float64 = 3.14159
和申明變量一樣,可以批量聲明多個(gè)常量;這比較適合聲明一組相關(guān)的常量。
const (
a int8 = 0x0F
c int16 = 0x0FFF
)
所有的常量的運(yùn)算都可以在編譯期完成,這樣可以減少運(yùn)行時(shí)的工作,也方便其他編譯優(yōu)化。當(dāng)操作數(shù)是常亮?xí)r,一些運(yùn)行時(shí)的錯(cuò)誤也可以在編譯時(shí)發(fā)現(xiàn),例如整數(shù)除零、字符串索引越界、任何導(dǎo)致無(wú)效浮點(diǎn)數(shù)的操作等。
柚子快報(bào)邀請(qǐng)碼778899分享:Golang學(xué)習(xí)-基本數(shù)據(jù)類(lèi)型
好文鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。