帶你學(xué)夠浪:Go語言基礎(chǔ)系列 - 8分鐘學(xué)復(fù)合類型

文章每周持續(xù)更新势似,原創(chuàng)不易拌夏,「三連」讓更多人看到是對我最大的肯定÷囊颍可以微信搜索公眾號「 后端技術(shù)學(xué)堂 」第一時間閱讀(一般比博客早更新一到兩篇)

對于一般的語言使用者來說 障簿,20% 的語言特性就能夠滿足 80% 的使用需求,剩下在使用中掌握栅迄≌竟剩基于這一理論,Go 基礎(chǔ)系列的文章不會刻意追求面面俱到毅舆,但該有知識點都會覆蓋西篓,目的是帶你快跑趕上 Golang 這趟新車。

Hurry up , Let's go !

前面我們學(xué)習(xí)過 Golang 中基礎(chǔ)數(shù)據(jù)類型憋活,比如內(nèi)置類型 int string bool 等岂津,其實還有一些復(fù)雜一點點,但很好用的復(fù)合類型悦即,類似 C 中的數(shù)組和 struct吮成、C++ 中的 map ,今天我們就來學(xué)習(xí) Go 中的復(fù)合類型辜梳。

通過本文的學(xué)習(xí)你將掌握以下知識:

  • 結(jié)構(gòu)體
  • 指針類型
  • 數(shù)組和切片
  • 映射類型

指針

指針不保存實際數(shù)據(jù)的內(nèi)容粱甫,而是保存了指向值的內(nèi)存地址 。用 & 對變量取內(nèi)存地址作瞄,用 * 來訪問指向的內(nèi)存魔种。這點和 C 中的指針是一樣,唯一不同的是 Go 中的指針不能運算粉洼。

    a := 3
    pa := &a // 用 `&` 對變量取內(nèi)存地址
    fmt.Println("point", a, *pa) // 用 `*` 來訪問指向的內(nèi)存

只聲明沒賦值的指針值是 nil 节预,代表空指針叶摄。

    var a0 *int // 只聲明沒賦值的指針是nil
    if a0 == nil {
        fmt.Println("point", "it is nil point")
    }

結(jié)構(gòu)體

與C中的結(jié)構(gòu)體類似, 結(jié)構(gòu)體是一種聚合的數(shù)據(jù)類型安拟,是由零個或多個任意類型的值聚合成的實體蛤吓。每個值稱為結(jié)構(gòu)體的成員,看例子:

type Test struct {
        a int
        b int
    }

語法上的不同看到了嗎糠赦? 每個結(jié)構(gòu)體字段之后沒有分號会傲,沒有分號寫起來還是很舒服的。

初始化

可以在定義的時候初始化

test := Test{1, 2}  // 定義結(jié)構(gòu)體變量并初始化

初始化部分結(jié)構(gòu)體字段

t2  = Test{a: 3}   //指定賦值Test.a為3  Test.b隱式賦值0

隱式初始化

t3  = Test{}       // .a .b都隱式賦值0

多個變量可以分組一起賦值

var (
    t1  = Test{8, 6}
    t2  = Test{a: 3}  //指定賦值Test.a  Test.b隱式賦值0
    t3  = Test{}      // .a .b都隱式賦值0
    pt4 = &Test{8, 6} // 指針
)

訪問成員

通過 . 運算來訪問結(jié)構(gòu)體成員拙泽,不區(qū)分結(jié)構(gòu)體類型或是結(jié)構(gòu)體指針類型淌山。

fmt.Println("struct", st0.a, st0.b) // 通過 . 運算來訪問結(jié)構(gòu)體成員

對于只聲明沒賦值的結(jié)構(gòu)體,其內(nèi)部變量被賦予零值顾瞻,下面我們聲明了 st0 但沒有對其賦值泼疑。

var st0 Test    
fmt.Println("struct", st0.a, st0.b) //輸出:struct 0 0

數(shù)組

數(shù)組是一個由固定長度的特定類型元素組成的序列,一個數(shù)組可以由零個或多個元素組成荷荤。 數(shù)組可以用下標(biāo)訪問元素退渗,下標(biāo)從 0 開始。

數(shù)組聲明后賦值

    var strarr [2]string // 數(shù)組聲明語法
    strarr[0] = "ready"
    strarr[1] = "go"

聲明賦值同時完成

    intarr := [5]int{6, 8, 9, 10, 7} // 聲明賦值同時完成

對于確定初始值個數(shù)的數(shù)組蕴纳,可以省略數(shù)組長度

    intarr := [...]int{6, 8, 9, 10, 7} // 聲明賦值同時完成

Slice 切片

切片是變長的序列会油,序列中每個元素都有相同的類型。slice 語法和數(shù)組很像古毛,只是沒有固定長度而已翻翩,切片底層引用一個數(shù)組對象,修改切片會修改原數(shù)組稻薇。

通過切片可以訪問數(shù)組的部分或全部元素体斩,正因為切片長度不是固定的,因此切片比數(shù)組更加的常用颖低。

聲明與初始化

常規(guī)初始化

簡短聲明并初始化切片

s0 := []int{1, 2, 3, 4, 5, 6} // 簡短聲明加賦值

聲明后再初始化

var s []int        // 聲明切片s
s = s0            // 用切片s0初始化切片s

聲明并初始化切片

var s00 []int = s0 // 用切片s0初始化切片s

切片的零值是 nil

// 切片的零值是nil 空切片長度和容量都是0
var nilslice []int
if nilslice == nil {
    fmt.Println("slice", "nilslice is nil ", len(nilslice), cap(nilslice))
}

make初始化

除了上述的常規(guī)初始化方法,還可以用 make 內(nèi)置函數(shù)來創(chuàng)建切片

// 內(nèi)建函數(shù)make創(chuàng)建切片弧烤,指定切片長度和容量
// make 函數(shù)會分配一個元素為零值的數(shù)組并返回一個引用了它的切片
s2 := make([]int, 4, 6) //創(chuàng)建元素都是0的切片s2, 長度為4忱屑,容量為6 第三個參數(shù)可以省略
fmt.Println("slice", len(s2), cap(s2), s2)

切片長度

長度表示切片中元素的數(shù)目,可用內(nèi)置函數(shù) len 函數(shù)得到暇昂。

切片容量

容量表示切片中第一個元素到引用的底層數(shù)組結(jié)尾所包含元素個數(shù)莺戒,可用內(nèi)置函數(shù) cap 求得。

切片區(qū)間

切片區(qū)間遵循「左閉右開」原則急波,

s0 := [5]int{6, 8, 9, 10, 7} // 數(shù)組定義
var slice []int = intarr[1:4]    //  創(chuàng)建切片slice 包含數(shù)組子序列

默認(rèn)上下界从铲。切片下界的默認(rèn)值為 0,上界默認(rèn)是該切片的長度澄暮。

fmt.Println("slice", s0[:], s0[0:], s0[:5], s0[0:5]) // 這四個切片相同

切片append操作

append 函數(shù)用于在切片末尾追加新元素名段。

添加元素也分兩種情況阱扬。

添加之后長度還在原切片容量范圍內(nèi)

s2 := make([]int, 4, 6) //創(chuàng)建元素都是0的切片s2, 長度為4,容量為6 第三個參數(shù)可以省略
s22 := append(s2, 2)    // append每次都是在最后添加伸辟,所以此時麻惶,s21 s22指向同一個底層數(shù)組
fmt.Println(s21, s22)   // [0 0 0 0 2] [0 0 0 0 2]

添加元素之后長度超出原切片容量

此時會分配新的數(shù)組空間,并返回指向這個新分配的數(shù)組的切片信夫。

下面例子中 s24 切片已經(jīng)指向新分配的數(shù)組窃蹋,s22 依然指向的是原來的數(shù)組空間,而 s24 已經(jīng)指向了新的底層數(shù)組静稻。

    s24 := append(s2, 1, 2, 3)
    fmt.Println(s24, s22) // s24 [0 0 0 0 1 2 3] [0 0 0 0 2]

二維切片

可以定義切片的切片警没,類似其他語言中的二維數(shù)組用法。參考代碼:

    s3 := [][]int{
        {1, 1, 1},
        {2, 2, 2},
    }
    fmt.Println(s3, s3[0], len(s3), cap(s3)) // 輸出: [[1 1 1] [2 2 2]] [1 1 1] 2 2

map 映射類型

在 Go 中 map 是鍵值對類型振湾,代表 keyvalue 的映射關(guān)系杀迹,一個map就是一個哈希表的引用 。

定義和初始化

下面這樣定義并初始化一個 map 變量

    m0 := map[int]string{
        0: "0",
        1: "1",
    }

也可以用內(nèi)置 make 函數(shù)來初始化一個 map 變量恰梢,后續(xù)再向其中添加鍵值對佛南。像下面這樣:

    m1 := make(map[int]string) // make 函數(shù)會返回給定類型的映射,并將其初始化備用
    if m1 != nil {
        fmt.Println("map", "m1 is not nil", m1) // m1 不是nil
    }
    m1[0] = "1"
    m1[1] = "2"

注意:只聲明不初始化的map變量是 nil 映射嵌言,不能直接拿來用嗅回!

    var m map[int]string // 未初始化的m零值是nil映射
    if m == nil {
        fmt.Println("map", "m is nil", m)
    }
    //m[0] = "1" // 這句引發(fā)panic異常, 映射的零值為 nil 摧茴。nil映射既沒有鍵绵载,也不能添加鍵。

元素讀取

使用語法:vaule= m[key] 獲取鍵 key 對應(yīng)的元素 vaule 苛白。

上面我們只用了一個變量來獲取元素娃豹,其實這個操作會返回兩個值,第一個返回值代表讀書的元素购裙,第二個返回值是代表鍵是否存在的 bool 類型懂版,舉例說明:

    v, st := m1[0]  // v是元素值,下標(biāo)對應(yīng)的元素存在st=true 否則st=false
    _, st1 := m1[0] // _ 符號表示忽略第一個元素
    v1, _ := m1[0]  // _ 符號表示忽略第二個元素    
    fmt.Println(v, st, v1, st1, m1[2]) // m1[2]不存在躏率,返回元素string的零值「空字符」

刪除元素

內(nèi)置函數(shù) delete 可以刪除 map 元素躯畴,舉例:

delete(m1, 1)  // 刪除鍵是 1 的元素

range 遍歷

range 用于遍歷 切片 或 映射。

數(shù)組或切片遍歷

當(dāng)使用for 循環(huán)和 range 遍歷數(shù)組或切片時薇芝,每次迭代都會返回兩個值蓬抄。第一個值為當(dāng)前元素的下標(biāo),第二個值為該下標(biāo)所對應(yīng)元素的一份副本夯到。

s1 := []int{1, 2, 3, 4, 5, 6}   
for key, vaule := range s1 {
    fmt.Println("range", key, vaule)
}

for key := range s1 { // 只需要索引嚷缭,忽略第二個變量即可
    fmt.Println("range", key)
}

for _, vaule := range s1 { // 只需要元素值,用'_'忽略索引
    fmt.Println("range", vaule)
}

map 遍歷

當(dāng)使用for 循環(huán)和 range 遍歷map 時,每次迭代都會返回兩個值阅爽。第一個值為當(dāng)前元素 key 路幸, 第二個值是 value

m0 := map[int]string{
    0: "0",
    1: "1",
}
fmt.Println("map", m0)

for k, v := range m0 { // range遍歷映射优床,返回key 和 vaule
    fmt.Println("map", "m0 key:", k, "vaule:", v)
}

總結(jié)

通過本文的學(xué)習(xí)劝赔,我們掌握了 Golang 中基本的控制流語句,利用這些控制語句加上一節(jié)介紹的變量等基礎(chǔ)知識胆敞,可以構(gòu)成豐富的程序邏輯着帽,你就能用 Golang 來做一些有意思的事情了。

感謝各位的閱讀移层,文章的目的是分享對知識的理解仍翰,技術(shù)類文章我都會反復(fù)求證以求最大程度保證準(zhǔn)確性,若文中出現(xiàn)明顯紕漏也歡迎指出观话,我們一起在探討中學(xué)習(xí).

今天的技術(shù)分享就到這里予借,我們下期再見。


創(chuàng)作不易频蛔,白票不是好習(xí)慣灵迫,如果在我這有收獲,動動手指「點贊」「關(guān)注」是對我持續(xù)創(chuàng)作的最大支持晦溪。

可以微信搜索公眾號「 后端技術(shù)學(xué)堂 」回復(fù)「資料」「1024」有我給你準(zhǔn)備的各種編程學(xué)習(xí)資料瀑粥。文章每周持續(xù)更新,我們下期見三圆!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末狞换,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子舟肉,更是在濱河造成了極大的恐慌修噪,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件路媚,死亡現(xiàn)場離奇詭異黄琼,居然都是意外死亡,警方通過查閱死者的電腦和手機整慎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進店門脏款,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人院领,你說我怎么就攤上這事」环裕” “怎么了比然?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長周循。 經(jīng)常有香客問我强法,道長万俗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任饮怯,我火速辦了婚禮闰歪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蓖墅。我一直安慰自己库倘,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布论矾。 她就那樣靜靜地躺著教翩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贪壳。 梳的紋絲不亂的頭發(fā)上饱亿,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機與錄音闰靴,去河邊找鬼彪笼。 笑死,一個胖子當(dāng)著我的面吹牛蚂且,可吹牛的內(nèi)容都是我干的配猫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼膘掰,長吁一口氣:“原來是場噩夢啊……” “哼章姓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起识埋,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤凡伊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后窒舟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體系忙,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年惠豺,在試婚紗的時候發(fā)現(xiàn)自己被綠了银还。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡洁墙,死狀恐怖蛹疯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情热监,我是刑警寧澤捺弦,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響列吼,放射性物質(zhì)發(fā)生泄漏幽崩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一寞钥、第九天 我趴在偏房一處隱蔽的房頂上張望慌申。 院中可真熱鬧,春花似錦理郑、人聲如沸蹄溉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽类缤。三九已至,卻和暖如春邻吭,著一層夾襖步出監(jiān)牢的瞬間餐弱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工囱晴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留膏蚓,地道東北人。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓畸写,卻偏偏與公主長得像驮瞧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子枯芬,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,654評論 2 354