Go語言同時提供了有符號和無符號的整數類型。
- 有符號整型:int、int8、int64、int32、int64
- 無符號整型:uint、uint8、uint64、uint32、uint64、uintptr
有符號整型范圍:-2^(n-1) 到 2^(n-1)-1
無符號整型范圍: 0 到 2^n-1
實際開發中由于編譯器和計算機硬件的不同,int 和 uint 所能表示的整數大小會在 32bit 或 64bit 之間變化。
uint在硬件開發中使用
用來表示 Unicode 字符的 rune 類型和 int32 類型是等價的,通常用于表示一個 Unicode 碼點。這兩個名稱可以互換使用。同樣,byte 和 uint8 也是等價類型,byte 類型一般用于強調數值是一個原始的數據而不是一個小的整數。
無符號的整數類型 uintptr,它沒有指定具體的 bit 大小但是足以容納指針。uintptr 類型只有在底層編程時才需要,特別是Go語言和C語言函數庫或操作系統接口相交互的地方。
在二進制傳輸、讀寫文件的結構描述時,為了保持文件的結構不會受到不同編譯目標平臺字節長度的影響,不要使用 int 和 uint
- 浮點型
Go語言支持兩種浮點型數:
float32 : 范圍 約1.4e-45 到 約3.4e38
float64 :范圍約4.9e-324 到 約1.8e308
func main() {myfloat := 3.2//%.2f 保留兩位小數fmt.Printf("%.2f", myfloat) //3.20
}
通常應該優先使用 float64 類型,因為 float32 類型的累計計算誤差很容易擴散,并且 float32 能精確表示的正整數并不是很大。
var f float32 = 1 << 24fmt.Println(f == f+1) //true
當這個整數賦值給float32類型的變量f時,會發生類型轉換。由于16777216超過了float32能夠精確表示的最大正整數(大約是3.4028235E+38),這個轉換會導致精度損失。實際上,16777216會被轉換為1.6777216e+07(即16777216.0),但這個轉換并不是精確的,因為float32只有7位有效數字。
因此,當你對f加1時,你其實是在對1.6777216e+07加1,但由于精度限制,結果仍然是1.6777216e+07。所以,f和f+1在float32的表示中是相等的,因此f == f+1的結果是true。
浮點數在聲明的時候可以只寫整數部分或者小數部分
a := .12341b := 1.fmt.Printf("%.5f,%1.f", a, b)
3. 布爾型
在Go語言中,以bool類型進行聲明:
var 變量名 bool
1
==,>,<,<=, >=,&&(AND),||(OR)等都會產生bool值
var aVar = 10
aVar == 5 // false
aVar == 10 // true
aVar != 5 // true
aVar != 10 // false
1
Go語言對于值之間的比較有非常嚴格的限制,只有兩個相同類型的值才可以進行比較,如果值的類型是接口(interface),那么它們也必須都實現了相同的接口。
如果其中一個值是常量,那么另外一個值可以不是常量,但是類型必須和該常量類型相同。
如果以上條件都不滿足,則必須將其中一個值的類型轉換為和另外一個值的類型相同之后才可以進行比較。
&&(AND),||(OR)是具有短路行為的,如果運算符左邊的值已經可以確定整個布爾表達式的值,那么運算符右邊的值將不再被求值。(&&優先級高于||)
var a = 10//因為a>11已經不滿足了,所以a < 30不會走,整個表達式為falseif(a > 11 && a < 30){fmt.Println("正確")}else{fmt.Println("錯誤")}//因為a > 5已經滿足了,所以a < 30不會走,整個表達式為trueif(a > 5 || a < 30){fmt.Println("正確")}else{fmt.Println("錯誤")}
布爾型數據只有true和false,且不能參與任何計算以及類型轉換
4. 字符類型
Go語言的字符有以下兩種:
- 一種是 uint8 類型,或者叫 byte 型,代表了 ASCII 碼的一個字符。
- 另一種是 rune 類型,代表一個 UTF-8 字符,當需要處理中文、日文或者其他復合字符時,則需要用到 rune 類型。rune 類型等價于 int32 類型。
byte 類型是 uint8 的別名,rune 類型是int32的別名
ASCII 碼的一個字符占一個字節
ASCII 定義 128 個字符,由碼位 0 – 127 標識。它涵蓋英文字母,拉丁數字和其他一些字符。
字符的定義:
Unicode 是 ASCII 的超集,它定義了 1,114,112 個代碼點的代碼空間。 Unicode 版本 10.0 涵蓋 139 個現代和歷史文本集(包括符文字母,但不包括 Klingon )以及多個符號集。
Go語言同樣支持 Unicode(UTF-8), 用rune來表示, 在內存中使用 int 來表示。
在書寫 Unicode 字符時,需要在 16 進制數之前加上前綴\u或者\U。如果需要使用到 4 字節,則使用\u前綴,如果需要使用到 8 個字節,則使用\U前綴。
Unicode 包中內置了一些用于測試字符的函數,這些函數的返回值都是一個布爾值,如下所示(其中 ch 代表字符):
- 判斷是否為字母:unicode.IsLetter(ch)
- 判斷是否為數字:unicode.IsDigit(ch)
- 判斷是否為空白符號:unicode.IsSpace(ch)
4.1 UTF-8 和 Unicode 有何區別?
Unicode 與 ASCII 類似,都是一種字符集。
字符集為每個字符分配一個唯一的 ID,我們使用到的所有字符在 Unicode 字符集中都有一個唯一的 ID,例如 a 在 Unicode 與 ASCII 中的編碼都是 97。漢字“你”在 Unicode 中的編碼為 20320,在不同國家的字符集中,字符所對應的 ID 也會不同。而無論任何情況下,Unicode 中的字符的 ID 都是不會變化的。
UTF-8 是編碼規則,將 Unicode 中字符的 ID 以某種方式進行編碼,UTF-8 的是一種變長編碼規則,從 1 到 4 個字節不等。編碼規則如下:
- 0xxxxxx 表示文字符號 0~127,兼容 ASCII 字符集。
- 從 128 到 0x10ffff 表示其他字符。
根據這個規則,拉丁文語系的字符編碼一般情況下每個字符占用一個字節,而中文每個字符占用 3 個字節。
廣義的 Unicode 指的是一個標準,它定義了字符集及編碼規則,即 Unicode 字符集和 UTF-8、UTF-16 編碼等
5. 字符串型
一個字符串是一個不可改變的字節序列,字符串可以包含任意的數據,但是通常是用來包含可讀的文本,字符串是 UTF-8 字符的一個序列。
字符串的定義:
var mystr string = "hello"
1
go語言從底層就支持UTF-8編碼。
UTF-8 是一種被廣泛使用的編碼格式,是文本文件的標準編碼。
由于該編碼對占用字節長度的不定性,在Go語言中字符串也可能根據需要占用 1 至 4 個字節,這與其它編程語言不同。
Go語言這樣做不僅減少了內存和硬盤空間占用,同時也不用像其它語言那樣需要對使用 UTF-8 字符集的文本進行編碼和解碼。
字符串是一種值類型,且值不可變,即創建某個文本后將無法再次修改這個文本的內容。
當字符為 ASCII 碼表上的字符時則占用 1 個字節
字符串中可以使用轉義字符來實現換行、縮進等效果,常用的轉義字符包括:
- \n:換行符
- \r:回車符
- \t:tab 鍵
- \u 或 \U:Unicode 字符
- \:反斜杠自身
var str string = "hahahah"fmt.Println(str)
如果使用``反引號,會被原樣進行賦值和輸出
var str string = `\thahahah`fmt.Println(str) //\thahahah
字符串是字節的定長數組,byte 和 rune 都是字符類型,若多個字符放在一起,就組成了字符串
比如 hello ,對照 ascii 編碼表,每個字母對應的編號是:104,101,108,108,111
var mystr01 string = "hello"var mystr02 [5]byte = [5]byte{104, 101, 108, 108, 111}fmt.Printf("myStr01: %s\n", mystr01)fmt.Printf("myStr02: %s", mystr02) //myStr02: hello
var str string = "hello,你好呀"//中文三字節,字母一個字節fmt.Println("len:", len(str)) //15
5.1 字符串的應用
一般的比較運算符(==、!=、<、<=、>=、>)是通過在內存中按字節比較來實現字符串比較的,因此比較的結果是字符串自然編碼的順序。
字符串所占的字節長度可以通過函數 len() 來獲取,例如 len(str)。
字符串的內容(純字節)可以通過標準索引法來獲取,在方括號[ ]內寫入索引,索引從 0 開始計數:
- 字符串 str 的第 1 個字節:str[0]
- 第 i 個字節:str[i - 1]
- 最后 1 個字節:str[len(str)-1]
需要注意的是,這種轉換方案只對純 ASCII 碼的字符串有效。
注意:獲取字符串中某個字節的地址屬于非法行為,例如 &str[i]。
ASCII字符使用len()函數
Unicode字符串長度使用utf8.RuneCountInString()函數
var str string = "hello,你好呀"fmt.Println("len:", len(str)) //15fmt.Println(utf8.RuneCountInString(str)) //9
字符串拼接符“+”
兩個字符串 s1 和 s2 可以通過 s := s1 + s2 拼接在一起。將 s2 追加到 s1 尾部并生成一個新的字符串 s,也可以使用“+=”來對字符串進行拼接:
var str string = "hello,你好呀,"var str2 string = "大帥哥"fmt.Println(str + str2) //hello,你好呀,大帥哥
除了使用+進行拼接,我們也可以使用WriteString()
如果從字符串 hello 碼神之路 中獲取 碼 該如何獲取呢?
直接索引對rune類型無效,可以使用string方法轉換
var str string = "hello 碼神之路"fmt.Println(string([]rune(str)[6]))
遍歷
unicode字符集使用for range進行遍歷,ascii字符集可以使用for range或者for循環遍歷
var str string = "hello 碼神之路"for _, val := range str {fmt.Println(string(val))}for _, val := range str {fmt.Printf("%c", val) //hello 碼神之路}
字符串的格式化
- print : 結果寫到標準輸出
- Sprint:結果會以字符串形式返回
var str string = "hello "var str2 string = "大帥哥"var stringBuilder bytes.BufferstringBuilder.WriteString(str)stringBuilder.WriteString(str2)res := fmt.Sprintf(stringBuilder.String())fmt.Println(res)
%c 單一字符
%T 動態類型
%v 本來值的輸出
%+v 字段名+值打印
%d 十進制打印數字
%p 指針,十六進制
%f 浮點數
%b 二進制
%s string
字符串查找
如何獲取字符串中的某一段字符?
- strings.Index(): 正向搜索子字符串
- strings.LastIndex():反向搜索子字符串
trace := "哈哈哈,你好天涯"index := strings.Index(trace, ",")fmt.Println(index) //9lastIndex := strings.LastIndex(trace, "涯")fmt.Println(lastIndex) //19
6. 類型轉換
在必要以及可行的情況下,一個類型的值可以被轉換成另一種類型的值。由于Go語言不存在隱式類型轉換,因此所有的類型轉換都必須顯式的聲明
a := 5.0
b := int(a)
類型轉換只能在定義正確的情況下轉換成功,例如從一個取值范圍較小的類型轉換到一個取值范圍較大的類型(將 int16 轉換為 int32)。
當從一個取值范圍較大的類型轉換到取值范圍較小的類型時(將 int32 轉換為 int16 或將 float32 轉換為 int),會發生精度丟失的情況。
只有相同底層類型的變量之間可以進行相互轉換(如將 int16 類型轉換成 int32 類型),不同底層類型的變量相互轉換時會引發編譯錯誤(如將 bool 類型轉換為 int 類型):
浮點數在轉換為整型時,會將小數部分去掉,只保留整數部分。
var myFloat float32 = 3.1415926fmt.Println(int32(myFloat)) //3
6.1 修改字符串
Golang語言的字符串是不可變的
修改字符串時,可以將字符串轉換為[]byte進行修改
[]byte和string可以通過強制類型轉換
案例:將8080改為8081
var str1 string = "localhost:8080"fmt.Println(str1)str := []byte(str1)str[len(str1)-1] = '1'fmt.Println(string(str)) //localhost:8081
字符串替換, 比如將 "Hello, 碼神之路Java教程" 替換為 "Hello, 碼神之路Go教程"
思路:
- 找到Java所在的位置
- 根據Java的長度將其分為兩部分
- 加上Go總共三部分,進行拼接
var str string = "Hello, 碼神之路Java教程"sorce := "Java"target := "Go"index := strings.Index(str, sorce)headStr := str[:index]lastStr := str[index+len(sorce):]targetStr := headStr + target + lastStrfmt.Println(targetStr)