03Go 型別總結
Go 型別總結
[TOC]
1、內建型別和內建函式
內建型別:
型別 | ⻓度 | 預設值 | 說明 |
---|---|---|---|
bool | 1 | false | 布林型只有true和false |
byte | 1 | 0 | uint8的別名 |
rune | 4 | 0 | Unicode Code Point, int32別名 |
int, uint | 4 或 8 | 0 | 有符號和無符號證書,根據系統可能32 或 64 位 |
int8, uint8 | 1 | 0 | -128 ~ 127, 0 ~ 255 |
int16, uint16 | 2 | 0 | -32768 ~ 32767, 0 ~ 65535 |
int32, uint32 | 4 | 0 | -21億 ~ 21 億, 0 ~ 42 億 |
int64, uint64 | 8 | 0 | |
float32 | 4 | 0.0 | 單精度浮點型 ,小數位:精確到7小數位 |
float64 | 8 | 0.0 | 雙精度浮點型,小數位:精確到15小數位 |
complex64 | 8 | 負數 | |
complex128 | 16 | ||
uintptr | 4 或 8 | nil | ⾜以儲存指標的 uint32 或 uint64 整數 |
array | 陣列,值型別 | ||
struct | 結構體,值型別 | ||
string | "" | UTF-8 字串 | |
slice | nil | 引⽤型別 | |
map | nil | 引⽤型別 | |
channel | nil | 引⽤型別 | |
interface | nil | 接⼝ | |
function | nil | 函式 | |
error | nil | 錯誤 |
內建函式:不需要匯入就能使用的函式 (瞭解即可)
函式 | 說明 |
---|---|
append | 追加元素到slice,返回修改後的slice |
close | 用來關閉channel |
delete | 從map中刪除key對應的value |
panic | 用來做錯誤處理 panic和rcover |
recover | 允許程式定義goroutine的panic動作 |
imag | 返回complex的實部,(complex,realimag:操作複數) |
real | 返回complex的虛部 |
make | 用來分配記憶體,返回Type本身(只應用於slice,map,channel) |
new | 用來分配記憶體,主要用來分配值型別。返回指向Type的指標 |
cap | 用於求最大容量,比如array,slice,channel,返回最大容量 |
copy | 用於賦值和連線slice,返回複製的數目 |
len | 返回長度 |
print、println | 底層列印函式,一般用fmt包的列印 |
2、型別轉換
- Go中不存在隱式轉換,所有型別轉換必須顯式宣告
- 轉換隻能發生在兩種相互相容的型別之間
- int(a)型別(被轉換變數)
3、變數
Go語言是靜態型別語言,不能在執行期間改變變數型別。使用關鍵字 var 定義變數,自動初始化為零值。如果提供初始化值,可省略變數型別,由編譯器自動推斷。
(1)單個變數宣告
var x int//使用var var s = "abc"//省略型別 s:="abc"//函式內部可以省略var
(2)多個變數宣告
var x, y, z int//定義多個 var s, n = "abc", 123//定義多個省略型別 var (//多個,多型別 a int b float32 ) //在函式內部,可⽤更簡略的 ":=" ⽅式定義變數 a,b:=128,"12"
(3)多變數賦值時,先計算所有相關值,然後再從左到右依次賦值
data, i := [3]int{0, 1, 2}, 0 i, data[i] = 2, 100 // (i = 0) -> (i = 2), (data[0] = 100)
(4)編譯器會將未使⽤的區域性變數當做錯誤
(5)注意重新賦值與定義新同名變數的區別。
同一程式碼塊,重新賦值記憶體地址不變。不同程式碼塊定義同名變數,記憶體地址不同。
(6)全域性變數、區域性變數、形參 以及優先順序
4、常量
常量值必須是編譯期可確定的數字(整型、浮點型、複數)、字串、布林值
(1)單個常量宣告
const s string = "Hello, World!" const s="Hello, World!"
(2)多個常量定義
const x, y int = 1, 2 // 多常量初始化 const (// 常量組 a, b = 10, 100 c bool = false )
(3)在常量組中,如不提供型別和初始化值,那麼視作與上⼀常量相同。
const ( s = "abc" x// x = "abc" )
(4)常量值還可以是 len、 cap、 unsafe.Sizeof 等編譯期可確定結果的函式返回值
const ( a = "abc" b = len(a) c = unsafe.Sizeof(b) )
(5)未使用的區域性常量不會引發編譯錯誤
(6)列舉:關鍵字 iota 定義常量組中從 0 開始按⾏計數的⾃增列舉值。
- 從 0 開始按⾏計數的自增
- 在同⼀常量組中,可以提供多個 iota,它們各⾃增⻓。
- 如果 iota ⾃增被打斷,須顯式恢復。
const ( _ = iota// iota = 0 KB int64 = 1 << (10 * iota) // iota = 1 MB// 與 KB 表示式相同,但 iota = 2 ) const (//在同⼀常量組中,可以提供多個 iota,它們各⾃增⻓。 A, B = iota, iota << 10 // 0, 0 << 10 C, D// 1, 1 << 10 ) //如果 iota ⾃增被打斷,須顯式恢復。 const ( A = iota // 0 B // 1 C = "c" // c D // c,與上⼀⾏相同。 E = iota // 4,顯式恢復。注意計數包含了 C、 D 兩⾏。 F // 5 )
5、指標
Go語言支援指標型別*T
,指標的指標**T
,以及包含包名字首的*package.T
。
- 操作符 "&" 取變數地址, "*" 透過指標訪問目標物件。
- 預設值 nil,沒有 NULL 常量。
- 不⽀持指標運算,不⽀持 "->" 運算子,直接⽤ "." 訪問目標成員。
指標宣告
var ip *int//宣告一個int值的指標變數 var sp *string//生成string值的指標變數 var str="hello" sp:= &str//:=定義指標 var p **int//宣告指標的指標
型別轉換:go語言指標是不允許指標型別轉換的。但是unsafe.Pointer可以變相實現運算
unsafe.Pointer型別用於表示任意型別的指標。有4個特殊的只能用於Pointer型別的操作:
1、 任意型別的指標可以轉換為一個Pointer型別值
2、 一個Pointer型別值可以轉換為任意型別的指標
3、 一個uintptr型別值可以轉換為一個Pointer型別值
4、 一個Pointer型別值可以轉換為一個uintptr型別值
func main() { d := struct { s string x int }{"abc", 100} p := uintptr(unsafe.Pointer(&d)) // *struct -> Pointer -> uintptr p += unsafe.Offsetof(d.x)// uintptr + offset p2 := unsafe.Pointer(p)// uintptr -> Pointer px := (*int)(p2)// Pointer -> *int *px = 200// d.x = 200 fmt.Printf("%#v\n", d) } //輸出: struct { s string; x int }{s:"abc", x:200}
注意: GC 把 uintptr 當成普通整數物件,它⽆法阻⽌ "關聯" 物件被回收。
6、字串
字串是不可變的值型別 ,內部用指標指向UTF-8位元組陣列。
在Go語言中,沒有字元型別,字元型別是rune型別,rune是int32的別稱。可使用 []byte() 獲取位元組,使用 []rune() 獲取字元,可對中文進行轉換。
- 預設值是空字串 ""。
- ⽤索引號訪問某位元組,如 s[i]。
- 不能⽤序號獲取位元組元素指標, &s[i] ⾮法。
- 不可變型別,⽆法修改位元組陣列。
- 位元組陣列尾部不包含 NULL。
(1)定義字串
//“abc” 雙引號定義字串 ``反引號定義非轉義字串,多行 str := `aaaa 可以跨行` str:="abc"
(2)+號連線字串:,"+" 必須在上一行末尾,否則導致編譯錯誤。連線是會產生新的字串。
當然還有函式連線,這個放到字串專題總結。如fmt.Sprintf()等
(3)單引號字元常量
單引號字元常量表⽰ Unicode Code Point,⽀持 uFFFF、 U7FFFFFFF、 xFF 格式。對應 rune 型別, UCS-4。
func main() { fmt.Printf("%T\n", 'a') var c1, c2 rune = '\u6211', '們' println(c1 == '我', string(c2) == "\xe4\xbb\xac") } //輸出: int32 // rune 是 int32 的別名 true true
(4)修改字串
要修改字串,可先將其轉換成 []rune 或 []byte,完成後再轉換為 string。⽆論哪種轉換,都會重新分配記憶體,並複製位元組陣列。
7、自定義型別和類型別名
可將型別分為命名和未命名兩⼤類。命名型別包括 bool、 int、 string 等,⽽ array、slice、 map 等和具體元素型別、⻓度等有關,屬於未命名型別。
具有相同宣告的未命名型別被視為同⼀型別。
- 具有相同基型別的指標
- 具有相同元素型別和⻓度的 array。
- 具有相同元素型別的 slice。
- 具有相同鍵值型別的 map。
- 具有相同元素型別和傳送⽅向的 channel。
- 具有相同欄位序列 (欄位名、型別、標籤、順序) 的匿名 struct。
- 簽名相同 (引數和返回值,不包括引數名稱) 的 function。
- ⽅法集相同 (⽅法名、⽅法簽名相同,和次序⽆關) 的 interface。
使用type關鍵字自定義型別:
//可⽤ type 在全域性或函式內定義新型別。 func main() { type bigint int64 var x bigint = 100 println(x) }
注意:新型別不是原型別的別名,除擁有相同資料儲存結構外,它們之間沒有任何關係,不會持有原型別任何資訊。除⾮目標型別是未命名型別,否則必須顯式轉換。