1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Go 專(zhuān)欄|復(fù)合數(shù)據(jù)類(lèi)型:字典 map 和 結(jié)構(gòu)體 struct

        共 5983字,需瀏覽 12分鐘

         ·

        2021-08-03 05:43

        樓下新開(kāi)了一家重慶砂鍋肥腸,擴(kuò)音喇叭一直在放:正宗的老重慶砂鍋肥腸,麻辣可口,老巴適了。

        正不正宗不知道,反正聽(tīng)口音,我以為我回東北了。

        本篇介紹復(fù)合數(shù)據(jù)類(lèi)型的最后一篇:字典和結(jié)構(gòu)體。內(nèi)容很重要,編程時(shí)用的也多,需要熟練掌握才行。

        本文所有代碼基于 go1.16.6 編寫(xiě)。

        字典

        字典是一種非常常用的數(shù)據(jù)結(jié)構(gòu),Go 中用關(guān)鍵詞 map 表示,類(lèi)型是 map[K]V。KV 分別是字典的鍵和值的數(shù)據(jù)類(lèi)型,其中鍵必須支持相等運(yùn)算符,比如數(shù)字,字符串等。

        創(chuàng)建字典

        有兩種方式可以創(chuàng)建字典,第一種是直接使用字面量創(chuàng)建;第二種使用內(nèi)置函數(shù) make

        字面量方式創(chuàng)建:

        // 字面量方式創(chuàng)建
        var m = map[string]int{"a"1"b"2}
        fmt.Println(m) // map[a:1 b:2]

        使用 make 創(chuàng)建:

        // 使用 make 創(chuàng)建
        m1 := make(map[string]int)
        fmt.Println(m1)

        還可以初始化字典的長(zhǎng)度。在已知字典長(zhǎng)度的情況下,直接指定長(zhǎng)度可以提升程序的執(zhí)行效率。

        // 指定長(zhǎng)度
        m2 := make(map[string]int10)
        fmt.Println(m2)

        字典的零值是 nil,對(duì)值是 nil 的字典賦值會(huì)報(bào)錯(cuò)。

        // 零值是 nil
        var m3 map[string]int
        fmt.Println(m3 == nillen(m3) == 0// true true
        // nil 賦值報(bào)錯(cuò)
        // m3["a"] = 1
        // fmt.Println(m3)    // panic: assignment to entry in nil map

        使用字典

        賦值:

        // 賦值
        m["c"] = 3
        m["d"] = 4
        fmt.Println(m) // map[a:1 b:2 c:3 d:4]

        取值:

        // 取值
        fmt.Println(m["a"], m["d"]) // 1 4
        fmt.Println(m["k"])         // 0

        即使在 Key 不存在的情況下,也是不報(bào)錯(cuò)的。而是返回對(duì)應(yīng)類(lèi)型的零值。

        刪除元素:

        // 刪除
        delete(m, "c")
        delete(m, "f"// key 不存在也不報(bào)錯(cuò)
        fmt.Println(m) // map[a:1 b:2 d:4]

        獲取長(zhǎng)度:

        // 獲取長(zhǎng)度
        fmt.Println(len(m)) // 3

        判斷鍵是否存在:

        // 判斷鍵是否存在
        if value, ok := m["d"]; ok {
            fmt.Println(value) // 4
        }

        和 Python 對(duì)比起來(lái)看,這個(gè)用起來(lái)就很爽。

        遍歷:

        // 遍歷
        for k, v := range m {
            fmt.Println(k, v)
        }

        引用類(lèi)型

        map 是引用類(lèi)型,所以在函數(shù)間傳遞時(shí),也不會(huì)制造一個(gè)映射的副本,這點(diǎn)和切片類(lèi)似,都很高效。

        package main

        import "fmt"

        func main() {
            ...

            // 傳參
            modify(m)
            fmt.Println("main: ", m) // main:  map[a:1 b:2 d:4 e:10]
        }

        func modify(a map[string]int) {
            a["e"] = 10
            fmt.Println("modify: ", a) //   modify:  map[a:1 b:2 d:4 e:10]
        }

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

        結(jié)構(gòu)體是一種聚合類(lèi)型,包含零個(gè)或多個(gè)任意類(lèi)型的命名變量,每個(gè)變量叫做結(jié)構(gòu)體的成員。

        創(chuàng)建結(jié)構(gòu)體

        首先使用 type 來(lái)自定義一個(gè)結(jié)構(gòu)體類(lèi)型 user,里面有兩個(gè)成員變量,分別是:nameage。

        // 聲明結(jié)構(gòu)體
        type user struct {
            name string
            age  int
        }

        結(jié)構(gòu)體的初始化有兩種方式:

        第一種是按照聲明字段的順序逐個(gè)賦值,這里需要注意,字段的順序要嚴(yán)格一致。

        // 初始化
        u1 := user{"zhangsan"18}
        fmt.Println(u1) // {zhangsan 18}

        這樣做的缺點(diǎn)很明顯,如果字段順便變了,那么凡是涉及到這個(gè)結(jié)構(gòu)初始化的部分都要跟著變。

        所以,更推薦使用第二種方式,按照字段名字來(lái)初始化。

        // 更好的方式
        // u := user{
        //     age: 20,
        // }
        // fmt.Println(u)    // { 20}
        u := user{
            name: "zhangsan",
            age:  18,
        }
        fmt.Println(u) // {zhangsan 18}

        未初始化的字段會(huì)賦值相應(yīng)類(lèi)型的零值。

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

        使用點(diǎn)號(hào) . 來(lái)訪(fǎng)問(wèn)和賦值成員變量。

        // 訪(fǎng)問(wèn)結(jié)構(gòu)體成員
        fmt.Println(u.name, u.age) // zhangsan 18
        u.name = "lisi"
        fmt.Println(u.name, u.age) // lisi 18

        如果結(jié)構(gòu)體的成員變量是可比較的,那么結(jié)構(gòu)體也是可比較的。

        // 結(jié)構(gòu)體比較
        u2 := user{
            age:  18,
            name: "zhangsan",
        }
        fmt.Println(u1 == u)  // false
        fmt.Println(u1 == u2) // true

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

        現(xiàn)在我們已經(jīng)定義一個(gè) user 結(jié)構(gòu)體了,假設(shè)我們?cè)俣x兩個(gè)結(jié)構(gòu)體 adminleader,如下:

        type admin struct {
            name    string
            age     int
            isAdmin bool
        }

        type leader struct {
            name     string
            age      int
            isLeader bool
        }

        那么問(wèn)題就來(lái)了,有兩個(gè)字段 nameage 被重復(fù)定義了多次。

        懶是程序員的必修課。有沒(méi)有什么辦法可以復(fù)用這兩個(gè)字段呢?答案就是結(jié)構(gòu)體嵌套。

        使用嵌套方式優(yōu)化后變成了這樣:

        type admin struct {
            u       user
            isAdmin bool
        }

        type leader struct {
            u        user
            isLeader bool
        }

        代碼看起來(lái)簡(jiǎn)潔了很多。

        匿名成員

        但這樣依然不是很完美,每次訪(fǎng)問(wèn)嵌套結(jié)構(gòu)體的成員變量時(shí)還是有點(diǎn)麻煩。

        // 結(jié)構(gòu)體嵌套
        a := admin{
            u:       u,
            isAdmin: true,
        }
        fmt.Println(a) // {{lisi 18} true}
        a.u.name = "wangwu"
        fmt.Println(a.u.name)  // wangwu
        fmt.Println(a.u.age)   // 18
        fmt.Println(a.isAdmin) // true

        這個(gè)時(shí)候就需要匿名成員登場(chǎng)了,不指定名稱(chēng),只指定類(lèi)型。

        type admin1 struct {
            user
            isAdmin bool
        }

        通過(guò)這種方式可以省略掉中間變量,直接訪(fǎng)問(wèn)我們需要的成員變量。

        // 匿名成員
        a1 := admin1{
            user:    u,
            isAdmin: true,
        }
        a1.age = 20
        a1.isAdmin = false

        fmt.Println(a1)         // {{lisi 20} false}
        fmt.Println(a1.name)    // lisi
        fmt.Println(a1.age)     // 20
        fmt.Println(a1.isAdmin) // false

        總結(jié)

        本文介紹了字典和結(jié)構(gòu)體,兩種很常用的數(shù)據(jù)類(lèi)型。雖然篇幅不長(zhǎng),但基本操作也都包括,寫(xiě)代碼肯定是沒(méi)有問(wèn)題的。更底層的原理和更靈活的用法就需要大家自己去探索和發(fā)現(xiàn)了。

        當(dāng)然,我也會(huì)在寫(xiě)完基礎(chǔ)專(zhuān)欄之后,分享一些更深層的文章,歡迎大家關(guān)注,交流。

        到目前為止,數(shù)據(jù)類(lèi)型就都介紹完了。

        先是學(xué)習(xí)了基礎(chǔ)數(shù)據(jù)類(lèi)型,包括整型,浮點(diǎn)型,復(fù)數(shù)類(lèi)型,布爾型和字符串型。然后是復(fù)合數(shù)據(jù)類(lèi)型,包括數(shù)組,切片,字典和結(jié)構(gòu)體。

        這些都是 Go 的基礎(chǔ),一定要多多練習(xí),熟練掌握。文中的代碼我都已經(jīng)上傳到 Github 了,有需要的同學(xué)可以點(diǎn)擊文末地址,自行下載。


        文章中的腦圖和源碼都上傳到了 GitHub,有需要的同學(xué)可自行下載。

        地址: https://github.com/yongxinz/gopher/tree/main/sc

        關(guān)注公眾號(hào) AlwaysBeta,回復(fù)「goebook」領(lǐng)取 Go 編程經(jīng)典書(shū)籍。

        Go 專(zhuān)欄文章列表:

        1. Go 專(zhuān)欄 | 開(kāi)發(fā)環(huán)境搭建以及開(kāi)發(fā)工具 VS Code 配置

        2. Go 專(zhuān)欄 | 變量和常量的聲明與賦值

        3. Go 專(zhuān)欄|基礎(chǔ)數(shù)據(jù)類(lèi)型:整數(shù)、浮點(diǎn)數(shù)、復(fù)數(shù)、布爾值和字符串

        4. Go 專(zhuān)欄|復(fù)合數(shù)據(jù)類(lèi)型:數(shù)組和切片 slice

        瀏覽 70
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操片在线| 中文字幕有码中文字幕无码 | 欧美逼逼网 | 性生交片免费看人无人区 | 蜜臀久久99精品久久久 | 亚洲一级特黄 | 天堂8在线视频 | 男性吹潮教程chinese视频 | 国产做爰又粗又大又大 | 在线无码电影 |