Go語言的數據類型
Go語言作為類C語言,支持常規的基礎數據類型的的同時,支持常用的高級數據類型。他們是:
- 整數,int,uint,int8,uint8,int16,uint16,int32,uint32,int64,uint64
- 浮點(小數),float32,float64
- 復數,complex
- 字符,byte,rune
- 字符串,string
- 布爾,bool
- 指針,pointor
- 數組,array
- nil
- 切片,slice。(引用類型)
- 映射,map
- 結構體,struct
- 接口,interface
- 函數,func()
本篇相當於一個類型索引。包含了Go語言中的全部類型。具體每種類型的操作,請參見具體章節!
2 整數,int
支持的整型分類很細,主要差異是占用的存儲空間不同。基於有無符號列出為:
有符號的:int,int8,int16,int32,int64
無符號的:uint,uint8,uint16,uint32,uint64
其中int, unit是基於處理器架構的。意味著會根據處理器來確定是32bit還是64bit。
使用時,常常使用int。或者使用int32保證兼容。
在類型推導時,推導的整型為int,其他長度整型需要在定義變量時強制聲明。
示例:
42
1024
-36
整型的默認值為0。
3 浮點數,float
支持IEEE-754標準浮點數。支持32bit和64bit的浮點數float32和float64。
示例:
1.0
3.14
0.618
4.2E10 // 4.2*10^10
浮點數的默認值為0。
4 復數,complex32,complex64
原生支持復數。
支持32bit+32bit復數complex64,和64bit+64bit的復數complex128。
5 字符,byte,rune
使用單引號定義字符型數據,字符指的是單個字符。有兩種byte和rune:
byte:單字節字符,是uint8的別名。用於存儲ASCII字符集字符
rune:多字節字符,是int32的別名。用於存儲unicode字符集字符。
在類型推導時,推導的字符型為rune。byte需要在定義變量時強制聲明。
‘c‘
‘康‘
字符的默認值是0。字符的本質就是整數型,根據字符集得到對應的字符。
6 字符串,string
原生支持字符串。使用雙引號("")或反引號(``)定義,內部是utf-8編碼。
雙引號:"", 用於單行字符串。
反引號:``,用於定義多行字符串,內部會原樣解析。
示例:
// 單行
"心有猛虎,細嗅薔薇"
// 多行
`
大風歌
大風起兮雲飛揚。
威加海內兮歸故鄉。
安得猛士兮守四方!
`
字符串支持轉義字符,列表如下:
- \r 回車符(返回行首)
- \n 換行符(直接跳到下一行的同列位置)
- \t 制表符
- \‘ 單引號
- \" 雙引號
- \\ 反斜杠
- \uXXXX Unicode字符碼值轉義
7 布爾型,bool
布爾型的值只可以是常量 true 或者 false。
示例:
var (
isFinished = false
)
8 指針,pointer
指針類型用於存儲變量地址。使用運算符 &
, *
完成操作。
使用運算符 p:=&v
可以獲取v變量的地址。p中的數據格式類似0xc0000b9528
,是一個內存地址的16進制表示。
使用運算符 *p
可以獲取指針p指向變量v的值。
如圖所示:
在Go語言中,指針主要用於:
- 類型指針,對指針指向的數據進行修改。函數調用時傳遞參數使用指針,避免值傳遞拷貝額外數據。註意類型指針不能進行偏移和運算。
- 切片,由指向起始元素的原始指針、元素數量和容量組成。
示例:p := 42 pv := &p *pv ++ // p == 43
9 數組,array
數組是一段固定長度的連續內存區域。是具有相同類型數據元素序列。元素類型支持任意內置類型。
數組從聲明時就確定長度,可以修改數組元素,但是數組不可修改長度。
使用 [長度]類型
進行數組的聲明。
示例:
// 默認值初始化
var nums [4]int // [0 0 0 0]
// 指定初始值
var position = [4]string{"east", "south", "west", "north"}
// 自動確定長度
var position = [...]string{"east", "south", "west", "north"}
會使用類型默認值初始化元素。
數組不是引用類型,變量間為值傳遞。
可以使用range配合循環結構完成遍歷,示例如下:
for k, v := range position {
fmt.Println(k, v)
}
// 結果
0 east
1 south
2 west
3 north
10 nil
nil,可以理解為未初始化引用。是以下類型的默認初始值:
- pointers -> nil
- slices -> nil
- maps -> nil
- channels -> nil
- functions -> nil
- interfaces -> nil
11 切片,slice
切片是一個擁有相同類型元素的可變長度的序列。與數組的固定長度不同,切片也被稱之為動態數組。
Go提供了4中方案定義切片:
make ( []Type ,length, capacity )
make ( []Type, length)
[]Type{}
[]Type{value1 , value2 , ... , valueN }
或者從數組或切片生成新切片:
slice [開始索引:結束索引]
- slice 表示目標切片對象。
- 開始索引和結束索引對應目標切片的索引。
- 不包含結束索引對應的元素
- 缺省開始索引,表示從頭到結束索引。
- 缺省結束索引,表示從開始索引到末尾。
- 兩者同時缺省時,全部切取,與切片本身等效。
- 兩者同時為0時,等效於空切片,一般用於切片復位。
var arr = [4]string{"a", "b", "c", "d"} var sli = arr[1:3] // ["b", "c"]
以從數組創建切片為例,理解切片,定義語法如上所示,下圖為slice:
切片的實現是由一個底層數組以及其上面的動態位置,尺寸來實現。由內部由指向起始元素的指針、元素數量length和容量capacity組成。其中:
- 指針ptr,用於指向切片在底層數組的起始位置。
- 尺寸len,用於記錄切片內元素數量。
- 容量cap,當前切片最大容量,也就是底層數組的容量。可以動態分配。
切片為引用類型。
切片的默認初始值為nil。
切片支持: len()尺寸, cap()容量, append()追加元素等操作。詳見切片的使用。
12 映射,map
Go語言中的鍵值對(key->value)集合,稱之為映射map。
創建語法:
var m = map[key_type]value_type{key1: value1, key2: value2}
var m = make(map[key_type]value_type)
示例,字符串型下標,字符串型值:
var m = make(map[string]string) //make()會分配內存空間,初始化。
m["east"] = "東"
m["west"] = "西"
fmt.Println(m["east"]) // 東
fmt.Println(m["west"]) // 西
// map演示
var m = map[string]string{"east": "東", "west": "西"}
支持遍歷操作,使用range:
for k, v := range mapVar {
fmt.Println(k, v)
}
映射是引用類型。
詳見切片操作。
13 結構體,struct
Go語言使用結構體來描述現實業務邏輯中實體。是自定義類型。結構體是由一系列數據構成的數據集合,一系列數據類型可以不同。
定義結構體,使用struct
關鍵字:
type 結構體名 struct {
成員1 類型
成員2 類型
…
}
示例:
// 定義Product結構
type Product struct {
// 兩個成員
name string
price float64
}
// 構造函數
func newProduct(name string, price float64) *Product {
return &Product{name, price}
}
// 成員方法,接收器方式
func (p *Product) getName() string {
return "《" + p.name + "》"
}
// 方法2
func (p *Product) setPrice(price float64) *Product {
p.price = price
return p
}
func main() {
// 構造Product型數據p1
var p1 = newProduct("BlockChain", 42.5)
// 訪問成員
fmt.Println(p1.name)
// 通過接收器訪問方法
fmt.Println(p1.getName())
var p2 = newProduct("GoLang", 30.5)
p2.setPrice(44.5)
fmt.Println(p2.price)
}
詳見結構體操作。
14 接口,interface
接口是一種協議,用來規範方法的調用和定義的協議,目的是保證設計的一致性,便於模塊化開發以及通訊。Go語言中,也視為一種類型。
定義語法:
type 接口名 interface {
方法1( 參數列表 ) 返回值類型列表
方法2( 參數列表 ) 返回值類型列表
…
}
可以理解成沒有方法體的方法。
示例:
// 定義Product結構
type Product struct {
// 兩個成員
name string
price float64
// say func()
}
// 構造函數
func newProduct(name string, price float64) *Product {
return &Product{name, price}
}
// 成員方法,接收器方式
func (p *Product) getName() string {
return "《" + p.name + "》"
}
// 方法2
func (p *Product) setPrice(price float64) *Product {
p.price = price
return p
}
// 定義接口
type ProductInterface interface {
getName() string
setPrice(price float64) *Product
}
func main() {
// 構造Product型數據p1
var p1 = newProduct("BlockChain", 42.5)
// pi為接口,為其賦值p1,就意味著使用接口規範p1,若p1不滿足接口定義則出錯
var pi ProductInterface = p1
// 利用接口調用方法
fmt.Println(pi.getName())
}
詳見接口操作
15 函數,func()
Go語言中,函數可以作為數據存儲變量中,此時變量為函數類型func()。可以通過該變量訪問到這個函數。可以用在結構體成員定義上。
語法示例:
func sayHello(name string) {
fmt.Println("Hello, ", name)
}
func main() {
// 函數本身就是函數類型
fmt.Printf("%T(%v)\n", sayHello, sayHello) // func(string)(0x48fe20)
// 賦值給變量
var f = sayHello
fmt.Printf("%T(%v)\n", f, f) // func(string)(0x48fe20)
// 匿名函數也是函數類型
var af = func() {
}
fmt.Printf("%T(%v)\n", af, af) // func()(0x490080)
}
參見函數使用。
完!
原文出自:小韓說課
微信關註:小韓說課
Go語言的數據類型