1. 程式人生 > >Go語言基礎(九)—— Go語言結構體、Go語言切片(Slice)、range遍歷、Go語言Map(集合)

Go語言基礎(九)—— Go語言結構體、Go語言切片(Slice)、range遍歷、Go語言Map(集合)

Go語言結構體

Go 語言中陣列可以儲存同一型別的資料,但在結構體中我們可以為不同項定義不同的資料型別。 結構體是由一系列具有相同型別或不同型別的資料構成的資料集合。 
結構體表示一項記錄,比如儲存圖書館的書籍記錄,每本書有以下屬性:

  • Title :標題 
  •  Author : 作者 
  •  Subject:學科 
  •  ID:書籍 ID 

定義結構體

 
 結構體定義需要使用 type 和 struct 語句。struct 語句定義一個新的資料型別,結構體有中有一個或多個成員。type 語句設定了結構體的名稱。結構體的格式如下:

type struct_variable_type struct { 
   member definition; 
   member definition; 
   ... 
   member definition; 
}

一旦定義了結構體型別,它就能用於變數的宣告,語法格式如下:

variable_name := structure_variable_type {value1, value2...valuen} 

 訪問結構體成員

如果要訪問結構體成員,需要使用點號 (.) 操作符,格式為:"結構體.成員名"。 結構體型別變數使用 struct 關鍵字定義,例項如下:

 

package main 
 
import "fmt" 
type Books struct { 
   title string 
   author string 
   subject string 
   book_id int 
} 
 
func main() {   
     var Book1 Books        /* 宣告 Book1 為 Books 型別 */   
     var Book2 Books        /* 宣告 Book2 為 Books 型別 */ 
 
   /* book 1 描述 */  
     Book1.title = "Go 語言"   
     Book1.author = "wek "   
     Book1.subject = "Go 語言教程" 
     Book1.book_id = 6495407 
 
   /* book 2 描述 */   
     Book2.title = "Python 教程"  
     Book2.author = "wek"    
     Book2.subject = "Python 語言教程" 
     Book2.book_id = 6495700 
 
   /* 列印 Book1 資訊 */ 
   fmt.Printf( "Book 1 title : %s\n", Book1.title) 
   fmt.Printf( "Book 1 author : %s\n", Book1.author) 
   fmt.Printf( "Book 1 subject : %s\n", Book1.subject) 
   fmt.Printf( "Book 1 book_id : %d\n", Book1.book_id) 
 
   /* 列印 Book2 資訊 */ 
   fmt.Printf( "Book 2 title : %s\n", Book2.title) 
   fmt.Printf( "Book 2 author : %s\n", Book2.author) 
   fmt.Printf( "Book 2 subject : %s\n", Book2.subject) 
   fmt.Printf( "Book 2 book_id : %d\n", Book2.book_id) 
}

結果為:

Book 1 title : Go 語言 
Book 1 author : wek 
Book 1 subject : Go 語言教程 
Book 1 book_id : 6495407 
Book 2 title : Python 教程 
Book 2 author : wek 
Book 2 subject : Python 語言教程 
Book 2 book_id : 6495700 

結構體作為函式引數

你可以像其他資料型別一樣將結構體型別作為引數傳遞給函式。

結構體指標

你可以定義指向結構體的指標類似於其他指標變數,格式如下:

var struct_pointer *Books

以上定義的指標變數可以儲存結構體變數的地址。檢視結構體變數地址,可以將 & 符號放置
於結構體變數前: 

struct_pointer = &Book1; 

使用結構體指標訪問結構體成員,使用 "." 操作符: 

struct_pointer.title; 

Go語言切片(Slice)

切片是 Go 語言中的關鍵資料型別,為序列提供了比陣列更強大的介面。與陣列不同,切片(slice)只是由它們包含的元素(而不是元素的數量)鍵入。要建立 非零長度的空切片,請使用內建 make()函式。 我們可以像陣列一樣設定和獲取字串的子串值。len()函式返回切片的長度。 除了這些基本操作之外,切片還支援更多,使它們比陣列更豐富。一個是內 置 append()函式,它返回包含一個或多個新值的切片。注意,需要接收 append()函式的返回值,因為可能得到一個新的 slice 值。 也可以複製切片。這裡建立一個與切片 s 相同長度的空切片 c,並從切片 s 複製到 c 中。切片支援具有語法為 slice[low:high]的切片運算子。 例如,這獲得元素 s[2],s[3]和 s[4]的切片。 這切片到(但不包括)s[5]。這切片從(包括)s[2]。可以在一行中宣告並初始化slice 的變數。 切片可以組成多維資料結構。內切片的長度可以變化,與多維陣列不同。 

定義切片

var identifier []type 

切片不需要說明長度。 或使用 make()函式來建立切片:

var slice1 []type = make([]type, len) 
 
也可以簡寫為 
 
slice1 := make([]type, len) 

 也可以指定容量,其中 capacity 為可選引數。

make([]T, length, capacity)

這裡 len 是陣列的長度並且也是切片的初始長度。

切片初始化

直接初始化切片,[]表示是切片型別,{1,2,3}初始化值依次是 1,2,3.其 cap=len=3 

s :=[] int {1,2,3 }

初始化切片s,是陣列arr的引用

s := arr[:] 

將 arr 中從下標 startIndex 到 endIndex-1 下的元素建立為一個新的切片 

s := arr[startIndex:]

預設 endIndex 時將表示一直到 arr 的最後一個元素 

s := arr[:endIndex] 

預設 startIndex 時將表示從 arr 的第一個元素開始

s1 := s[startIndex:endIndex]

通過切片 s 初始化切片 s1

s :=make([]int,len,cap) 

通過內建函式 make()初始化切片 s,[]int 標識為其元素型別為 int 的切片

Len()和cap()函式

切片是可索引的,並且可以由 len() 方法獲取長度。 切片提供了計算容量的方法 cap() 可以測量切片最長可以達到多少。

空切片(nil)

一個切片在未初始化之前預設為 nil,長度為 0

package main 
 
import "fmt" 
 
func main() { 
   var numbers []int 
 
   printSlice(numbers) 
 
   if(numbers == nil){       fmt.Printf("切片是空的") 
   } 
} 
 
func printSlice(x []int){ 
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) 
}

結果為:

len=0 cap=0 slice=[] 切片是空的 

append()和copy()函式

如果想增加切片的容量,我們必須建立一個新的更大的切片並把原分片的內容都拷貝過來。 下面的程式碼描述了從拷貝切片的 copy 方法和向切片追加新元素的 append 方法。

package main 
 
import "fmt" 
 
func main() { 
   var numbers []int 
   printSlice(numbers) 
 
   /* 允許追加空切片 */ 
   numbers = append(numbers, 0) 
   printSlice(numbers) 
 
   /* 向切片新增一個元素 */ 
   numbers = append(numbers, 1) 
   printSlice(numbers) 
 
   /* 同時新增多個元素 */ 
   numbers = append(numbers, 2,3,4) 
   printSlice(numbers) 
 
   /* 建立切片 numbers1 是之前切片的兩倍容量*/ 
   numbers1 := make([]int, len(numbers), (cap(numbers))*2) 
 
   /* 拷貝 numbers 的內容到 numbers1 */ 
   copy(numbers1,numbers) 
   printSlice(numbers1)    
} 
 
func printSlice(x []int){ 
   fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x) 
} 

結果為:

len=0 cap=0 slice=[] 
len=1 cap=1 slice=[0] 
len=2 cap=2 slice=[0 1] 
len=5 cap=6 slice=[0 1 2 3 4] 
len=5 cap=12 slice=[0 1 2 3 4] 

Go語言範圍(Range)

Go 語言中 range 關鍵字用於 for 迴圈中迭代陣列(array)、切片(slice)、通道(channel)或集合
(map)的元素。在陣列和切片中它返回元素的索引值,在集合中返回 key-value 對的 key 值。

package main 
import "fmt" 
func main() {     //這是我們使用 range 去求一個 slice 的和。使用陣列跟這個很類似 
    nums := []int{2, 3, 4} 
    sum := 0 
    for _, num := range nums { 
        sum += num 
    } 
    fmt.Println("sum:", sum)     //在陣列上使用 range 將傳入 index 和值兩個變數。上面那個例子我們不需要使用該元素的序號, 所以我們使用空白符"_"省略了。有時侯我們確實需要知道它的索引。 
    for i, num := range nums { 
        if num == 3 { 
            fmt.Println("index:", i) 
        } 
    }     //range 也可以用在 map 的鍵值對上。 
    kvs := map[string]string{"a": "apple", "b": "banana"} 
    for k, v := range kvs { 
        fmt.Printf("%s -> %s\n", k, v) 
}  //range 可以只迭代 map 的 key 值 
  for k := range kvs { 
        fmt.Println("key:", k) 
} 
 
    //range 也可以用來列舉 Unicode 字串。第一個引數是字元的索引,第二個是字元(Unicode 的 值)本身。 
    for i, c := range "go" { 
        fmt.Println(i, c) 
    } 
}

結果為:

sum: 9 
index: 1 
a -> apple 
b -> banana 
key: a 
key: b 
0 103 
1 111

Go語言Map(集合)

Map 是一種無序的鍵值對的集合。Map 最重要的一點是通過 key 來快速檢索資料,key 類似
於索引,指向資料的值。 Map 是一種集合,所以我們可以像迭代陣列和切片那樣迭代它。不過,Map 是無序的,我們無法決定它的返回順序,這是因為 Map 是使用 hash 表來實現的。

定義Map

可以使用內建函式 make 也可以使用 map 關鍵字來定義 Map: 

/* 宣告變數,預設 map 是 nil */ 
var map_variable map[key_data_type]value_data_type 
 
/* 使用 make 函式 */ 
map_variable := make(map[key_data_type]value_data_type) 

如果不初始化 map,那麼就會建立一個 nil map。nil map 不能用來存放鍵值對

package main 
 
import "fmt" 
 
func main() { 
   var countryCapitalMap map[string]string    /* 建立集合 */ 
   countryCapitalMap = make(map[string]string) 
       /* map 插入 key-value 對,各個國家對應的首都 */ 
   countryCapitalMap["France"] = "Paris" 
   countryCapitalMap["Italy"] = "Rome" 
   countryCapitalMap["Japan"] = "Tokyo" 
   countryCapitalMap["India"] = "New Delhi" 
       /* 使用 key 輸出 map 值 */ 
   for country := range countryCapitalMap { 
      fmt.Println("Capital of",country,"is",countryCapitalMap[country]) 
   } 
       /* 檢視元素在集合中是否存在 */ 
   captial, ok := countryCapitalMap["United States"]    /* 如果 ok 是 true, 則存在,否則不存在 */ 
   if(ok){ 
      fmt.Println("Capital of United States is", captial)   
   }else { 
      fmt.Println("Capital of United States is not present")  
   } 
}

結果為:

Capital of France is Paris 
Capital of Italy is Rome 
Capital of Japan is Tokyo 
Capital of India is New Delhi 
Capital of United States is not present

delete()函式

delete() 函式用於刪除集合的元素, 引數為 map 和其對應的 key。例項如下:

 

package main 
 
import "fmt" 
 
func main() {       /* 建立 map */ 
   countryCapitalMap := map[string] string {"France":"Paris","Italy":"Rome","Japan":
"Tokyo","India":"New Delhi"} 
       fmt.Println("原始 map")    
       /* 列印 map */ 
   for country := range countryCapitalMap { 
      fmt.Println("Capital of",country,"is",countryCapitalMap[country]) 
   } 
       /* 刪除元素 */ 
   delete(countryCapitalMap,"France"); 
   fmt.Println("Entry for France is deleted")   
       fmt.Println("刪除元素後 map")    
    

   /* 列印 map */ 
   for country := range countryCapitalMap { 
      fmt.Println("Capital of",country,"is",countryCapitalMap[country]) 
   } 
} 
原始 map 
Capital of France is Paris 
Capital of Italy is Rome 
Capital of Japan is Tokyo 
Capital of India is New Delhi 
Entry for France is deleted 刪除元素後 map 
Capital of Italy is Rome 
Capital of Japan is Tokyo 
Capital of India is New Delhi