五、類型
Go語言內置以下這些基礎類型:
布爾類型: bool。
整型: int8、 byte、 int16、 int、 uint、 uintptr等。
浮點類型: float32、 float64。
複數類型: complex64、 complex128。
字符串: string。
字符類型: rune。
錯誤類型: error。
此外, Go語言也支持以下這些複合類型:
指針( pointer)
數組( array)
切片( slice)
字典( map)
通道( chan)
結構體( struct)
接口( interface)
1、布爾類型
Go語言中的布爾類型與其他語言基本一致,關鍵字也爲bool,可賦值爲預定義的true和
false
2、整形
支持整形類型如下:
注意:int和int32在Go語言裏被認爲是兩種不同的類型,編譯器也不會幫你自動做類型轉換,必須使用強制類型轉換進行轉換
go 語言的所有的運算和C語言相同,除了取反符號,c語言取反是 ~, 而go 是^
3、浮點型
Go語言定義了兩個類型float32和float64,其中float32等價於C語言的float類型,float64等價於C語言的double類型
浮點型比較:
因爲浮點數不是一種精確的表達方式,所以像整型那樣直接用==來判斷兩個浮點數是否相等是不可行的,這可能會導致不穩定的結果。
下面是一種推薦的替代方案:
import "math"
// p爲用戶自定義的比較精度,比如0.00001
func IsEqual(f1, f2, p float64) bool {
return math.Fdim(f1, f2) < p
}
4、複數類型
表示法:
var value1 complex64
或者:
value3 := complex(3.2, 12)
5、字符串
聲明:
var str string
Go語言內置的函數len()來取字符串的長度
6、字符型
在Go語言中支持兩個字符類型,一個是byte(實際上是uint8的別名),代表UTF-8字符串的單個字節的值;另一個是rune,代表單個Unicode字符
7、數組
以下爲常見的數組聲明方法:
元素訪問
可以使用數組下標來訪問數組中的元素。與C語言相同,數組下標從0開始, len(array)-1
則表示最後一個元素的下標
Go語言還提供了一個關鍵字range,用於便捷地遍歷容器中的元素
例如:
for i, v := range array {
fmt.Println("Array element[", i, "]=", v)
}
8、數組切片
數組的長度在定義之後無法再次修改;數組是值類型,每次傳遞都將產生一份副本。顯然這種數據結構無法完全滿足開發者的真實需求。不用失望, Go語言提供了數組切片( slice)這個非常酷的功能來彌補數組的不足。初看起來,數組切片就像一個指向數組的指針,實際上它擁有自己的數據結構,而不僅僅是個指針。數組切片的數據結構可以抽象爲以下3個變量:
a:一個指向原生數組的指針
b:數組切片中的元素個數;
c:數組切片已分配的存儲空間。
從底層實現的角度來看,數組切片實際上仍然使用數組來管理元素,因此它們之間的關係讓C++程序員們很容易聯想起STL中std::vector和數組的關係。基於數組,數組切片添加了一系列管理功能,可以隨時動態擴充存放空間,並且可以被隨意傳遞而不會導致所管理的元素被重複複製。
創建數組切片:
有兩種方式,基於數組和直接創建
基於數組:
注意: 基於數組創建的數組切片,數組切片和數組使用的是同一空間,則修改數組,同時也修改了切片
參考slice.go
package main
import "fmt"
func main() {
// 先定義一個數組
var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
// 基於數組創建一個數組切片
var mySlice []int = myArray[:5]
fmt.Println("Elements of myArray: ")
for _, v := range myArray {
fmt.Print(v, " ")
}
fmt.Println("\nElements of mySlice: ")
for _, v := range mySlice {
fmt.Print(v, " ")
}
fmt.Println()
}
直接創建:
Go語言提供的內置函數make()可以用於靈活地創建數組切片
例如:
創建一個初始元素個數爲5的數組切片,元素初始值爲0:
mySlice1 := make([]int, 5)
創建一個初始元素個數爲5的數組切片,元素初始值爲0,並預留10個元素的存儲空間:
mySlice2 := make([]int, 5, 10)
直接創建並初始化包含5個元素的數組切片:
mySlice3 := []int{1, 2, 3, 4, 5}
動態增減元素:
可動態增減元素是數組切片比數組更爲強大的功能。與數組相比,數組切片多了一個存儲能力( capacity)的概念,即元素個數和分配的空間可以是兩個不同的值。
假如你明確知道當前創建的數組切片最多可能需要存儲的元素個數爲50,那麼如果你設置的存儲能力小於50,比如20,那麼在元素超過20時,底層將會發生至少一次這樣的動作——重新分配一塊“夠大”的內存,並且需要把內容從原來的內存塊複製到新分配的內存塊,這會產生比較明顯的開銷。給“夠大”這兩個字加上引號的原因是系統並不知道多大才是夠大,所以只是一個簡單的猜測。比如,將原有的內存空間擴大兩倍,但兩倍並不一定夠,所以之前提到的內存重新分配和內容複製的過程很有可能發生多次,從而明顯降低系統的整體性能。但如果你知道最大是50並且一開始就設置存儲能力爲50,那麼之後就不會發生這樣非常耗費CPU的動作,從而達到空間換時間的效果。
數組切片支持Go語言內置的cap()函數和len()函數,cap()函數返回的是數組切片分配的空間大小,而len()函數返回的是數組切片中當前所存儲的元素個數
參考代碼:slice2.go
package main
import "fmt"
func main() {
mySlice := make([]int, 5, 10)
fmt.Println("len(mySlice):", len(mySlice))
fmt.Println("cap(mySlice):", cap(mySlice))
}
基於數組切片創建數組切片:
類似於數組切片可以基於一個數組創建,數組切片也可以基於另一個數組切片創建,且創建方式與基於數組相同
內容複製:
數組切片支持Go語言的另一個內置函數copy(),用於將內容從一個數組切片複製到另一個數組切片。如果加入的兩個數組切片不一樣大,就會按其中較小的那個數組切片的元素個數進行復制。
9、map
參考代碼 map1.go
package main
import "fmt"
// PersonInfo是一個包含個人詳細信息的類型
type PersonInfo struct {
ID string
Name string
Address string
}
func main() {
var personDB map[string] PersonInfo
personDB = make(map[string] PersonInfo)
// 往這個map裏插入幾條數據
personDB["12345"] = PersonInfo{"12345", "Tom", "Room 203,..."}
personDB["1"] = PersonInfo{"1", "Jack", "Room 101,..."}
// 從這個map查找鍵爲"1234"的信息
person, ok := personDB["1234"]
// ok是一個返回的bool型,返回true表示找到了對應的數據
if ok {
fmt.Println("Found person", person.Name, "with ID 1234.")
} else {
fmt.Println("Did not find person with ID 1234.")
}
}
參考如上代碼:
聲明:
var personDB map[string] PersonInfo
創建:
personDB = make(map[string] PersonInfo)
也可以選擇是否在創建時指定該map的初始存儲能力,下面的例子創建了一個初始存儲能力爲100的map:
myMap = make(map[string] PersonInfo, 100)
也可以直接初始化:
myMap = map[string] PersonInfo{
"1234": PersonInfo{"1", "Jack", "Room 101,..."},
}
操作
插入: personDB["12345"] = PersonInfo{"12345", "Tom", "Room 203,..."}
刪除:delete(myMap, "12345")
如果“12345”這個鍵不存在,那麼這個調用將什麼都不發生,也不會有什麼副作用。但是如果傳入的map變量的值是nil,該調用將導致程序拋出異常( panic)。