Golang——数据类型使用细节详解
數據類型:
計算機存儲設備最小信息單位是位(bit),最小的存儲單元是字節(byte)
占用字節的不同,所表示能存儲的數據長度不同
作用:
說明數據的數據的結構,便于后面定義變量、參數傳遞等
默認值:
| 整型 | 0 |
| 浮點型 | 0.0 |
| 字符串 | "" |
| 布爾類型 | false |
數據類型說明:
| bool | 有 | 布爾類型 | 1 | 只有true或false,默認是false |
| byte | 無 | 字節型 | 1 | 等價于uint8,當要存儲字符的時候可以byte |
| rune | 有 | 字符類型 | 4 | 專用于存儲unicode編碼,等價于uint32 |
| int | 有 | 整型 | 4或8 | 32位系統4個字節 64位系統8個字節int占用多大取決于操作系統 |
| uint | 無 | 整型 | 4或8 | 32位系統4個字節 64位系統8個字節 |
| int8 | 有 | 整型 | 1 | -128 ~ 127 |
| int16 | 有 | 整型 | 2 | -32768 ~ 32767 |
| int32 | 有 | 整型 | 4 | -2147483648 到 2147483647 |
| int64 | 有 | 整型 | 8 | 0 到 18446744073709551615(1844京) |
| uint8 | 無 | 整型 | 1 | 0 ~ 255 |
| uint16 | 無 | 整型 | 2 | 0 ~ 65535 |
| uint32 | 無 | 整型 | 4 | 0 到 4294967295(42億) |
| uint64 | 無 | 整型 | 8 | -9223372036854775808到 9223372036854775807 |
| float32 | 有 | 浮點型 | 4 | 小數位精確到7位 |
| float64 | 有 | 浮點型 | 8 | 小數位精確到15位 |
| complex64 | 有 | 復數類型 | 8 | |
| complex128 | 有 | 復數類型 | 16 | |
| uintptr | 有 | 整型 | 4或8 | ?以存儲指針的uint32或uint64整數 |
| string | 有 | 字符串 | utf-8字符串 |
有符號和無符號的區別
有符號的,長度第一位會存數據類型,剩余的長度才是數據。無符號的全部都可以存數據。前面有u就是無符號,沒有u就是有符號
有符號和無符號如何選擇:
如果只存整數就使用無符號的,因為范圍更大,如果存的有負數就用有符號的。
能用小的就不要選擇大的,比如年齡就用byte(0 ~ 255)
如何查看變量的數據類型:
fmt.Printf("%T", 變量名):// 輸出不換行,可以指定輸出的變量類型如何查看數據類型占用的字節大小:
fmt.Printf("%d", unsafe.Sizeof(num))// unsafe.Sizeof(num):返回指定變量占用的字節數基本數據類型和引用類型區別:
基本數據類型:int、float、bool、string、數組、結構體
引用類型:指針、切片、map、管道、接口
區別:
基本數據類型的變量是直接存數據的,通常在棧中分配的
引用數據類型的變量是先存一個內存地址,這個變量分配的空間才是存數據的,通常在堆中分配的。當沒有引用變量的時候,會由GC回收變成垃圾
整型:
演示:
func test() {var age uint = -10println(age) // 報錯,不支持負數 }浮點類型:
- 關于數學運算的包里默認都是用的float64,日常使用也盡量使用float64的就行了
- 浮點數可能會造成精度損失,64位的要比32位的更精準
演示:
func test02() {var sum float64 = 123.456789sum2 := 123.456789 // 如果使用的是自動推導類型,默認就是float64類型的fmt.Printf("%f\n", sum) //123.456789fmt.Printf("%.2f\n", sum) // 使用".數字"可以保留小數位數并四舍五入 123.46fmt.Printf("%T", sum2) // float64 %T可以打印出變量的類型 }布爾類型:
- 布爾類型也叫bool類型,布爾類型的取值要么是true,要么是false
- bool適合做邏輯運算,一般用在流程控制語句里
- 使用bool關鍵字進行定義,默認值為false
字符類型:
- Golang沒有字符類型,類似java的char,如果要存儲單個字符,一般使用byte保存。
- 字符串本質是一串固定長度字符連接起來的字符序列,但是在Golang里是由單個字節連接起來的
- 如果需要保存的變量值大于255時使用byte會溢出,可以使用int代替byte保存數據
- Go語言的字符使用的是UTF-8編碼標識Unicode文本,所以Go統一使用了UTF-8沒有亂碼的問題出
- 字符的本質也是一個整數,直接輸出的時候是按照對應的UTF-8編碼的碼值運算的,所以字符可以參與運算。
- 字符變量賦值后,通過c%可以打印出該數字對應的unicode字符
- 用單引號引起來的字符,單引號里只能有一個字符,數據類型為byte
點擊查看ASCLL碼表
演示:
//b := 'b'var b byte = 'a'fmt.Println(b) // 打印結果不是b,是98,fmt.Printf("%c", b) // c%可以打印出該數字對應的unicode字符var z int = 'a'fmt.Println(z)字符串類型:
- 字符串本質是一串固定長度字符連接起來的字符序列,但是在Golang里是由單個字節連接起來的
- 字符串中有一個隱藏的結束標志\0
- Go語言默認為UTF-8編碼存儲Unicode字符,所以Go統一使用了UTF-8沒有亂碼的問題出現
- 字符串一旦賦值就不能修改了,字符串是不可變的
- 雙引號格式會識別字符串里的轉義字符
- 反引號以字符串的原生形式輸出,在反引號里的內容全部都是普通文本,包括換行和特殊字符,可以實現防止攻擊、輸入源代碼的效果
- 默認空字符串不是nil,而是""
在golang中做字符串拼接的時候如果需要換行,需要把加號放在上一行,否則會報錯
允許以索引號訪問字節數組(并非字符),但不能獲取數組元素地址
func main() {s := "abc"println(s[1])println(&s[1]) // 錯誤: cannot take the address of s[1] }以切片語法(起始和結束索引號)返回子串時,其內部依舊指向原字節數組
func main() {s := "abcdefg"s1 := s[:3] // 從頭開始,僅指定結束索引位置s2 := s[1:4] // 指定開始和結束位置,返回[start, end)s3 := s[2:] // 指定開始位置,返回后面全部內容println(s1, s2, s3)// reflect.StringHeader 和 string 頭結構相同。// unsafe.Pointer用于指針類型轉換。fmt.Printf("%#v\n", (*reflect.StringHeader)(unsafe.Pointer(&s)))fmt.Printf("%#v\n", (*reflect.StringHeader)(unsafe.Pointer(&s1))) }StringHeader源碼
type StringHeader struct {Data uintptr // 存方指針,指向的是原數組Len int // 字符串的長度 }使用for遍歷字符串時,分byte和rune兩種方式
func main() {s := "itzhuzhu"for i := 0; i < len(s); i++ { // bytefmt.Printf("%d: [%c]\n", i, s[i])}fmt.Println("-------------------")for i, c := range s { // rune,返回數組索引號,以及Unicode字符fmt.Printf("%d: [%c]\n", i, c)} }用加法操作符拼接字符串時,每次都需重新分配內存。如此,在構建“超大”字符串時,性能就顯得極差
func test() string {var s stringfor i := 0; i < 1000; i++ {s += "a"}return s } func BenchmarkTest(b *testing.B) {for i := 0; i < b.N; i++ {test()} }改進方法就是預先分配足夠的內存空間。常用方法是用strings.Join函數,它會統計所有參數長度,并一次性完成內存分配操作
func test() string {s := make([]string, 1000) // 分配足夠的內存,避免中途擴張底層數組for i := 0; i < 1000; i++ {s[i] = "a"}return strings.Join(s, "") }改進后的算法有巨大提升。還有bytes.Buffer也可完成相同操作,且性能相當
func test() string {var b bytes.Bufferb.Grow(1000) // 分配足夠的內存,避免中途擴張底層數組for i := 0; i < 1000; i++ {b.WriteString("a")}return b.String() }對于數量較少的字符串格式化拼接,可使用fmt.Sprintf、text/template等方法
引用類型:
- Go的引用類型特指slice、map、channel這三種,相比數字、數組等類型,引用類型擁有更復雜的存儲結構。除分配內存外,它們還需初始化一系列屬性,諸如指針、長度,甚至包括哈希分布、數據隊列等。
- 內置函數new依指定類型數據長度分配內存,返回指針。而引用類型則必須使用make有 數創建,編譯器將make轉換為目標類型專用創建函數(或指令),以完成內存分配和屬性初始化。
rune:
類型rune專門用來存儲Unicode Code Point,它是int32的別名,相當于UCS-4/UTF-32 編碼格式。使用單引號的字面量,其默認類型就是rune
除[ ]rune外,還可直接在rune、byte、string間進行轉換
func main() {r := '哈's := string(r) // rune to string b := byte(r) // rune to byte s2 := string(b) // byte to string r2 := rune(b) // byte to rune fmt.Println(s, b, s2, r2) }總結
以上是生活随笔為你收集整理的Golang——数据类型使用细节详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux lua 性能,systemT
- 下一篇: linux飞行模式自动开机,解决 win