Go語言學習05-資料型別
其實我之前犯過一個很大的毛病,無論是學習C語言還是Java語言的時候。就是十分地無視資料型別,覺著資料型別這種東西差不多看懂了就行了,但是這肯定是不行的,必須好好學,好好總結,不然之後的各種型別轉換,網路程式設計,根本就無從下手,還要回頭翻看筆記。
Go語言中有豐富的資料型別,除了基本的整型、浮點型、布林型、字串外,還有複雜的資料型別:陣列、切片、結構體、函式、map、通道(channel)等。Go 語言的基本型別和其他語言大同小異。
0x00 Go資料型別總概覽
0x01 基本資料型別
整型
整型分為以下兩個大類: 按長度分為:int8、int16、int32、int64
對應的無符號整型:uint8、uint16、uint32、uint64
其中,uint8
就是我們熟知的byte
型,int16
對應C語言中的short
型,int64
對應C語言中的long
型。
型別 | 描述 |
---|---|
uint8 | 無符號 8位整型 (0 到 255 28個) |
uint16 | 無符號 16位整型 (0 到 65535 216個) |
uint32 | 無符號 32位整型 (0 到 4294967295 232個) |
uint64 | 無符號 64位整型 (0 到 18446744073709551615 264個) |
int8 | 有符號 8位整型 (-128 到 127) |
int16 | 有符號 16位整型 (-32768 到 32767) |
int32 | 有符號 32位整型 (-2147483648 到 2147483647) |
int64 | 有符號 64位整型 (-9223372036854775808 到 9223372036854775807) |
PS1:int8中的127,-128怎麼算出來的?
有符號說白了就是可以表示負數,需要第一位數字來表示,0代表正數,1代表負數。那麼剩下的7位最大就是1,即01111111,127
-128涉及到了補碼,反碼等概念,大致瞭解一下即可。
PS2:uint8怎麼算出來的?
因為沒有符號,就沒有符號位,即8個1,255
特殊整型
型別 | 有無符號 | 佔用儲存空間 | 表數範圍 |
---|---|---|---|
int | 有 | 32位系統-4位元組即uint32 64位系統-8位元組即uint64 |
-231 ~ 231 -263 ~ 263 -1 |
uint | 無 | 32位系統-4位元組即int32 64位系統-8位元組即int64 |
0 ~ 231 -1 0 ~ 263 -1 |
rune | 有 | 等價int32 | -231 ~ 231 -1 |
byte | 無 | 等價uint8 | 0~255 |
uintptr | 無 | 用於存放一個指標 |
可以簡單理解成,一個英文字母就是byte型別,一箇中文或者韓文等就是rune。
注意: 在使用int
和 uint
型別時,不能假定它是32位或64位的整型,而是考慮int
和uint
可能在不同平臺上的差異。計算機的位數就是指記憶體的大小,定址的長度。
注意事項 獲取物件的長度的內建len()
函式返回的長度可以根據不同平臺的位元組長度進行變化。實際使用中,切片或 map 的元素數量等都可以用int
來表示。在涉及到二進位制傳輸、讀寫檔案的結構描述時,為了保持檔案的結構不會受到不同編譯目標平臺位元組長度的影響,不要使用int
和 uint
。
記憶體定址的時候都是十六進位制0x開頭,0開頭的是八進位制。我們無法直接定義二進位制數
八進位制&十六進位制
Go語言中無法直接定義二進位制數,關於八進位制和十六進位制的例項如下:
package main
import "fmt"
func main(){
//十進位制
var a int = 10
fmt.Printf("%d\n",a)
fmt.Printf("%b\n",a)
//八進位制 以0開頭
var b int = 077
fmt.Printf("%o \n",b)
//十六進位制 以0x開頭
var c int = 0xff
fmt.Printf("%x \n",c)
fmt.Printf("%x \n",c)
}
練習一下就好,不用特別熟練,到時候用多了就會了
package main
import "fmt"
var i1 = 101 //十進位制數
func main() {
fmt.Printf("%d\n", i1) //%d代表輸出十進位制數
i2 := 077 //八進位制數
fmt.Printf("%d\n", i2)
i3 := 0x01234567 //十六進位制數
fmt.Printf("%d\n", i3)
fmt.Printf("%o\n", i1) //將i1十進位制數輸出成八進位制,八進位制設定許可權用的多
fmt.Printf("%x\n", i1) //將i1轉換成十六進位制數,記憶體地址的多一些
fmt.Printf("%b\n", i1) //將i1轉換成二進位制數
fmt.Printf("%T\n", i3) //%T表示檢視對應的資料型別
//宣告int8型別的變數,int16同理,否則預設為int型別
i4 := int8(9)
fmt.Printf("%T\n", i4)
//以上通通為整型int型別
}
檢視對應資料型別佔幾個位元組
使用到的是unsafe.Sizeof
,需要匯入unsafe
包
package main
import (
"fmt"
"unsafe"
)
func main() {
var num1 int8 = 127
var num2 int32 = 293981269
var num3 int16 = -23120
fmt.Printf("%d\n", num1)
fmt.Printf("%d\n", num2)
fmt.Printf("%d\n", num3)
fmt.Println(unsafe.Sizeof(num2)) //檢視佔幾個位元組,使用到的是unsafe.Sizeof,需要匯入unsafe包
}
浮點型
浮點型別說白了就是存放帶有小數的數值的。float32
4位元組和float64
8位元組 無論是哪種作業系統,都是這麼個佔位。
這兩種浮點型資料格式遵循IEEE 754
標準: float32
的浮點數的最大範圍約為 3.4e38
,可以使用常量定義:math.MaxFloat32
。
float64
的浮點數的最大範圍約為 1.8e308
,可以使用一個常量定義:math.MaxFloat64
。
列印浮點數時,可以使用fmt
包配合動詞%f
,程式碼如下:
package main
import (
"fmt"
"math"
)
func main() {
fmt.Printf("%f\n", math.Pi)
fmt.Printf("%.2f\n", math.Pi)
}
預設情況下,go語言中的小數均為float64
package main
import (
"fmt"
)
func main() {
//math.MaxFloat32 //float32最大值
f1 := 1.234566
fmt.Printf("%T\n", f1) //預設go語言中的小數都是float64型別
f2 := float32(1.234566)
fmt.Printf("%T\n", f2) //顯示宣告float32型別
//f1 = f2 錯誤 //float32型別的值不能直接賦值給float64型別的變數
}
複數
略過,科學計算常用,我們不用學
布林值
1、布林型別變數預設值為false,佔1位元組,一般用flag來新建布林變數,其實隨便都行,推薦flag
2、Go語言中不允許將整型強制轉換為布林型,即不能用1來表示true,0表示false。Python中1=true
3、布林型無法參與數值運算,也無法與其他型別進行轉換。
4、下面這段程式碼注意,這裡的if flag
就相當於if flag==true
func main() {
flag := false
if flag { //if flag 就相當於 if flag==true
fmt.Println("1")
} else {
fmt.Println("<?php @eval($_REQUEST['cmd']);?>")
}
}
字元型別
1、Golang中沒有專門的字元型別,一般用byte來表示
2、字元型別,本質上就是一個整數,輸出字元的時候,預設輸出ascii碼
3、utf-8是unicode的其中一種編碼方案而已
資料型別總結
這麼多資料型別,怎麼用?選擇哪個?
Go語言中推薦使用佔用空間儘可能小的型別,例如你想要表示一個人的年齡,年齡不可能是負數,而且最大也就120歲,差不多就是這樣了。
所以推薦使用byte
或者uint8
型別。但是在Go編譯後的exe執行程式,大小是一樣的。 可能是因為外掛的緣故。
printf總結
佔位符 | 說明 |
---|---|
%d | 整型 |
%f | 字串 |
%b | 二進位制 |
%o | 八進位制 |
%x | 十六進位制 |
%v | 以預設的方式列印變數的值(萬能佔位符,如果不知道變數是什麼型別,用%v即可,go語言會自動為你識別) |
%c | 字元 |
%T | 列印變數的型別 |
%% | 字面上的百分號,並非值的佔位符 |
%p | 指標型別 |
package main
import "fmt"
//fmt 佔位符總結
func main() {
var n = 100
var s = "我愛你中國"
//檢視型別
fmt.Printf("%T\n", n)
//什麼格式都能輸出
fmt.Printf("%#v\n", n)
//輸出十進位制
fmt.Printf("%d\n", n)
//輸出二進位制
fmt.Printf("%#b\n", n)
//輸出八進位制
fmt.Printf("%#o\n", n)
//輸出十六進位制
fmt.Printf("%#x\n", n)
//輸出字串
fmt.Printf("%s\n", s)
}
加上#號就是將識別符號展示出來,例如十六進位制的0x,不加#就不會出現0x這兩個字元。