加油幹 golang入坑系列

生活常識發表於2017-11-29

還是提醒一下,裡面有段子,不都是技術。 衝著技術來的,慢走不送。沒有版權,但可以給我發郵件(ztao8607@gmail.com)

在我的發小朋友中,終於最後一位打光棍的要結婚了。 說實話,真心不容易。相親七八次,女方年齡上至32,下至23。跨度之大,範圍之廣,在我的發小界相當罕見。 捫心自問,程式設計師都怎麼了?為什麼找個女朋友結婚會如此艱難。 是coder們不解風情?還是被島國妹子矇蔽了心靈?若說木訥,內向。那恐怕是對碼農們最大的誤解了,在他們一副不願說話的面具之下都暗藏著一顆洶湧澎湃的內心,時時刻刻在迸發著靈感。但至於這份靈感幾分用於妹子身上,那就尚未可知了。也見過舌尖口利,口若懸河的屌絲,但這種狀態經常出現在與人爭論技術問題之時,如若對面站的是一個萌妹子,恐怕再多的hello world也要return回肚子裡面。所以,我這位發小找不到另一半,的確是有原因的。 還好,經過全方位不歇的努力,終於找到了一個懂得撬開這位愣頭青口舌的妹子。所以,藉此祝願二位喜結良緣,白頭到老,擼起袖子加油幹!

書接上文,繼續來聊Golang中常見的資料型別。

在上篇中,說到了String。本節來看陣列Array。若你還有印象,想必在大學課堂之上肯定會有一門<資料結構>的課程。這門課程應該是計算機專業的奠基之課,學好了這門課,即便你不會寫程式碼也不耽誤你找份好工作。如果又學好了演算法,即便你不會寫程式碼,也不耽誤你去BAT實習。

而陣列就是一種常見的資料結構。 這裡沒法從資料結構的角度來講陣列,因為我自認對此並不精通,講不好不如不講。 有興趣,建議翻看大學資料結構的教材,看懂那本就夠了。

Golang的陣列從資料結構的角度來說,和其它語言沒什麼區別。都是鏈式儲存資料,儲存相同型別的資料。陣列下標同樣從0開始計數,通過[]來順序訪問。例如:

intList[0] intList[1] ... intList[99]

宣告陣列最常用的方法是下面這種:

var arrayname[SIZE] type

這是最常用的單維陣列(只有一個維度的陣列),相對應的會存在多維陣列,例如二維陣列。二維陣列的每一項都是另外一個陣列,因此可以理解成存放陣列的陣列。

當使用上面語句宣告變數時,Size必須是一個大於零的整數常量,而型別可以是任何合法的資料型別(包括內建的基本型別或者自定義的資料型別)。

例如,我們宣告一個長度為10的整型陣列:

var intList[10] int

在<準備衝鋒>一節中,可以看到變數宣告之外,如果是基本資料型別的變數,golang會自動完成初始化。 那陣列呢?golang會不會自動完成初始化。你可以自己動手寫段程式碼試一下。如果不想寫,直接拿走下面的程式碼:

package main

import (
    "fmt"
)

func main() {
    var intList [10]int
    fmt.Println(intList[1])
    fmt.Println(intList[9])
}

任意訪問兩個元素,結果都是0. 換成其它型別,看看結果。實際結果表明,如果是基本資料型別,golang同樣會對陣列元素進行初始化。在上例當中,所有元素都初始化成了0. 如果想初始化其它資料怎麼辦?Easy,使用下面的語法:

var name = [SIZE]type{ value, value .... }

從語法上面來看,就是一個二合一。 首先宣告陣列,然後對陣列中每個元素進行賦值,藉此完成資料初始化的目的。比如下面:

var intList = [5]int{1,2,3,4,5}

在執行一下程式碼,看看結果:

package main

import (
    "fmt"
)

func main() {
    var intList = [5]int{1,2,3,4,5}
    fmt.Println(intList[1])
    fmt.Println(intList[4])
}

這種方式是常用的初始化方式,再說一點不太常用,但面試的時候容易被人提及的(正常情況下,使用概率低於10%).

隱式長度

var intList = []int{1,3,4,5,6}

事先不宣告長度,依靠後面初始值的長度來確定陣列長度,沒啥可說的,技巧而已。

比這個剛常用的是:

var intList []int
intList = append(intList,10)

但此時intList已經變成切片型別了。 切片和陣列還是有所不同的,在下節會講到切片型別,這裡只劇透一下。

陣列初始化完成之後,在後面的程式中都可以直接使用了。 而使用的方式,就是通過下標依次取出進行賦值或者取值操作。例如:

// 直接拷貝個原始碼,用來說明問題
package main

import "fmt"

func main() {
   var n [10]int
   var i,j int

   for i = 0; i < 10; i++ {
      n[i] = i + 100 
   }

   for j = 0; j < 10; j++ {
      fmt.Printf("Element[%d] = %d\n", j, n[j] )
   }
}

Golang最基本的陣列用法就是這些,在開始的時候說過,最常用的是一維陣列,多維陣列使用不算太多(尤其超過二維的陣列,用之甚少),因此使用一點篇幅來說一下多維陣列的使用。

首先是多維陣列的宣告,看著負責,其實不難:

var name [SIZE1][SIZE2][SIZE3]....type

既然是陣列,就要遵循陣列的規範,無論是多維陣列還是單維陣列,其中的元素必須是同一種資料型別,所以可以看到最後只有一種type。

而上面多個SIZE的個數表示的是維度,上面有三個SIZE表示的是三維(例如經常說的長高寬,如果你非要理解成那個三維,隨便你,也沒錯)。如果只有[SIZE1][SIZE2]就表示是二維。

多維陣列的初始化和一維一樣(其實我們可以將多維陣列降維成一維),看下面:

var a = [3][4]int{  
   {0, 1, 2, 3} ,   
   {4, 5, 6, 7} ,   
   {8, 9, 10, 11}   
}

a是一個二維陣列,在第一維上面有三個元素,每個元素是一個陣列(這個陣列是一個儲存四個元素的單維陣列)。所以這個陣列的初始化,就是同時完成多個陣列的初始化。

多維陣列的訪問,仍然遵循下標訪問的規則。 例如需要取出上面陣列中的8,那就是 a[2][0]。 因為8所在的陣列是a陣列的第三個元素,所以先取出a[2],而這個a[2]是一個陣列,8是這個陣列的第一個元素,所以a[2][0]就是8。

熟能生巧,唯手熟爾。 所以遇到不明白的地方,多寫幾段程式碼看看效果。

最後問個小問題,讓你來回答。

提問:[5]int 和 []int 是不是同一種資料型別

回答: XXXX

還是那句話,寫段程式碼驗證一下。

package main

import "fmt"

func main() {
    var s []int
    s = append(s, 10)
    printArray(s)
}

func printArray(s []int) {
    fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)
}

如果把printArray的引數由[]int 替換成 [5]int,看看什麼效果。 恩,報錯。 會提示你型別不一致。這點是剛開始寫golang程式碼時容易混淆的地方,[5]int是陣列型別,而[]int則是切片型別。因此會報錯。

在實際程式設計經驗中,陣列使用率反而不如切片高。這又是為何呢? 還不點個star,訂閱下一節。

如果您認為此文章對您有所幫助,請您點選推薦。進步來源於思想的碰撞,所以歡迎大家踴躍留言評論。

相關文章