繼Golang學習系列第二天:變數、常量、數據類型和流程語句之後,今天開始學習數據類型之高級類型: 派生類型。 學過java的人都知道,java其實就8種基本類型:byte、short、int、long、float、double、char、boolean,但它有引用數據類型:字元串、數組、集合、類、 ...
繼Golang學習系列第二天:變數、常量、數據類型和流程語句之後,今天開始學習數據類型之高級類型: 派生類型。
學過java的人都知道,java其實就8種基本類型:byte、short、int、long、float、double、char、boolean,但它有引用數據類型:字元串、數組、集合、類、介面等。
而golang也有這樣的劃分,基本類型(Golang學習系列第二天已學過)和派生類型(不叫引用類型),派生類型有以下幾種:數組類型、切片類型、Map類型、結構體類型(struct)、指針類型(Pointer)、函數類型、介面類型(interface)、Channel 類型。
1. 數組類型
數組是具有相同數據類型的元素序列。 數組在聲明中定義了固定的長度,因此不能擴展超過該長度。 數組聲明為
var variable_name [SIZE] variable_type
讓我們以代碼舉例如下
package main
import "fmt"
func main() {
var city [5]string
city[0] = "北京"
city[1] = "上海"
city[2] = "廣州"
city[3] = "深圳"
city[4] = "濮陽"
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
}
將變數city聲明為5個字元串的數組,執行輸出
不過也可以在聲明數組時設置數組條目,看簡潔版
package main
import "fmt"
func main() {
var city = [5]string{ "北京", "上海","廣州","深圳","濮陽"}
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
//簡寫版
othercity := [5]string{ "北京", "上海","廣州", "深圳","濮陽"}
fmt.Printf("%q", othercity)
}
輸出結果
甚至,當您傳遞值時,可以使用省略號來使用隱式長度
package main
import "fmt"
func main() {
var city = [5]string{ "北京", "上海","廣州","深圳","濮陽"}
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
//簡寫版
othercity := [5]string{ "北京", "上海","廣州", "深圳","濮陽"}
fmt.Printf("%q\n", othercity)
//隱士長度
other_city := [...]string{ "北京", "上海","廣州", "深圳","濮陽"}
fmt.Printf("%q", other_city)
}
輸出結果
以不同方式列印數組
註意我們使用帶Printf的fmt包以及如何使用%q“動詞”來列印每個引用的元素。
如果我們使用Println或%s動詞,我們將得到不同的結果
package main
import "fmt"
func main() {
//不同方式列印數組
other_city := [...]string{ "北京", "上海","廣州", "深圳","濮陽"}
fmt.Println("不同方式列印數組")
fmt.Println(other_city)
fmt.Printf("%s\n", other_city)
fmt.Printf("%q", other_city)
}
執行後輸出如圖
多維數組
您還可以創建多維數組,示例代碼:
package main
import "fmt"
func main() {
var multi [2][3]int
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
multi[i][j] = i + j
}
}
fmt.Println("二維數組: ", multi)
}
輸出結果
2. 切片Slices類型
切片包裝數組可為數據序列提供更通用,更強大和更方便的介面。 除了具有明確維數的項(例如轉換矩陣)外,Go中的大多數數組編程都是使用切片而不是簡單數組完成的。
切片包含對基礎數組的引用,如果您將一個切片分配給另一個,則兩個切片都引用同一數組。 如果函數採用slice參數,則對slice的元素所做的更改將對調用者可見,這類似於將指針傳遞給基礎數組。
切片指向值數組,並且還包含長度。 切片可以調整大小,因為它們只是另一個數據結構之上的包裝。
例如, []T is a slice with elements of type T 表示[] T是具有T類型元素的切片。
舉個小例子
package main
import "fmt"
func main() {
var city = []string{ "北京", "上海","廣州","深圳","濮陽"}
fmt.Println(city[0], city[1], city[2], city[3], city[4])
fmt.Println(city)
}
2.1 切分切片
可以對切片進行切片,以創建一個指向相同數組的新切片值。表達式為
slice[start:end]
表示計算從start到end-1(含)的元素的一部分。
註意:start和end是表示索引的整數。
下麵舉個小demo
package main
import "fmt"
func main() {
var city = []string{ "北京", "上海","廣州","深圳","濮陽","鄭洲"}
fmt.Println(city)
fmt.Println(city[1:4])
// missing low index implies 0
fmt.Println(city[:3])
// [2 3 5]
// missing high index implies len(s)
fmt.Println(city[4:])
}
輸出結果
2.2 製造切片
除了通過立即傳遞值(切片文字)來創建切片之外,還可以使用make關鍵字創建切片。 您創建一個特定長度的空切片,然後填充每個條目。
package main
import "fmt"
func main() {
fmt.Println("準備用make方式創建切片")
cities := make([]string, 3)
cities[0] = "鄭洲"
cities[1] = "濮陽"
cities[2] = "安陽"
fmt.Printf("%q", cities)
}
輸出結果:
它通過分配清零的數組並返回引用該數組的切片來工作。
2.3 附加到切片
可以通過append方式附加值到切片中
package main
import "fmt"
func main() {
//附加到切片
other_cities := []string{}
other_cities = append(other_cities, "濮陽")
fmt.Println(other_cities)
}
看輸出結果
也可以同時附加多個值到切片中,示例代碼同時包括兩個城市鄭洲和濮陽
package main
import "fmt"
func main() {
//附加多值到切片
other_cities := []string{}
other_cities = append(other_cities, "鄭洲","濮陽")
fmt.Println(other_cities)
}
輸出結果
甚至您還可以使用省略號將切片附加到另一個切片
package main
import "fmt"
func main() {
fmt.Println("準備用make方式創建切片")
cities := make([]string, 3)
cities[0] = "鄭洲"
cities[1] = "濮陽"
cities[2] = "安陽"
fmt.Printf("%q\n", cities)
//附加切片到切片
other_cities := []string{"南京"}
other_cities = append(other_cities, cities...)
fmt.Println(other_cities)
}
輸出結果
註意: 省略號是該語言的內置功能,這意味著該元素是一個集合。 我們無法將字元串類型([] string)類型的元素附加到字元串切片中,只能附加字元串。 但是,在切片後使用省略號(...),表示要附加切片的每個元素。 因為我們要從另一個片段追加字元串,所以編譯器將接受操作,因為類型是匹配的。
您顯然無法將[] int類型的切片附加到[] string類型的另一個切片中。
2.4 複製切片
切片也可以複製。 在這裡,我們創建一個與other_cities長度相同的空切片copycities,並從other_cities複製到copycities中。
package main
import "fmt"
func main() {
fmt.Println("準備用make方式創建切片")
cities := make([]string, 3)
cities[0] = "鄭洲"
cities[1] = "濮陽"
cities[2] = "安陽"
fmt.Printf("%q\n", cities)
//附加多值到切片
other_cities := []string{"南京"}
other_cities = append(other_cities, cities...)
fmt.Println(other_cities)
//拷貝切片
fmt.Println("準備用copy方式創建切片")
copycities := make([]string, len(other_cities))
copy(copycities, other_cities)
fmt.Println("copycities:", copycities)
}
輸出結果
2.5 切片長度
您可以隨時使用len檢查切片的長度。
package main
import "fmt"
func main() {
fmt.Println("準備用make方式創建切片")
cities := make([]string, 3)
cities[0] = "鄭洲"
cities[1] = "濮陽"
cities[2] = "安陽"
fmt.Printf("%q\n", cities)
//附加多值到切片
other_cities := []string{"南京"}
other_cities = append(other_cities, cities...)
fmt.Println(other_cities)
//列印切片長度
fmt.Println(len(cities))
countries := make([]string, 42)
fmt.Println(len(countries))
}
輸出結果
2.6 零片
切片的零值為nil。 無切片的長度和容量為0。
package main
import "fmt"
func main() {
//零片
var temp []int
fmt.Println(temp, len(temp), cap(temp))
if temp == nil {
fmt.Println("nil!")
}
}
輸出結果
3. map類型
Map 是一種無序的鍵值對的集合,Map 最重要的一點是通過 key 來快速檢索數據,key 類似於索引,指向數據的值。
Map 是一種集合,所以我們可以像迭代數組和切片那樣迭代它。不過,Map 是無序的,我們無法決定它的返回順序,這是因為 Map 是使用 hash 表來實現的。
package main
import "fmt"
func main() {
users := map[string]int{
"admin": 0,
"donguangming": 1,
"student": 2,
}
fmt.Printf("%#v", users)
}
輸出結果
當不使用上述map時,使用前必須使用make(不是新的)創建map。 nil映射為空,無法分配給它。
package main
import "fmt"
type User struct {
name string
age int
city string
}
var user map[string]User
func main() {
//通過make創建
user = make(map[string]User)
user["dgm"] = User{"董廣明", 99, "南京"}
fmt.Println(user["dgm"])
}
輸出結果
3.1 操作map
3.1.1 在map中插入或更新元素
m[key] = elem
3.1.2 查詢一個元素
elem = m[key]
3.1.3 刪除一個元素
delete(m, key)
3.1.4 測試鍵是否存在並且有值
elem, ok = m[key]
如果鍵在m中,則確定為true。 如果不是,則ok為false,elem為map元素類型的零值。 同樣,從map中讀取時(如果沒有按鍵)則結果是map元素類型的零值。
綜上合起來代碼如下