<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 5983字,需瀏覽 12分鐘

           ·

          2021-08-03 05:43

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

          正不正宗不知道,反正聽口音,我以為我回東北了。

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

          本文所有代碼基于 go1.16.6 編寫。

          字典

          字典是一種非常常用的數(shù)據(jù)結(jié)構(gòu),Go 中用關(guān)鍵詞 map 表示,類型是 map[K]VKV 分別是字典的鍵和值的數(shù)據(jù)類型,其中鍵必須支持相等運算符,比如數(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í)行效率。

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

          字典的零值是 nil,對值是 nil 的字典賦值會報錯。

          // 零值是 nil
          var m3 map[string]int
          fmt.Println(m3 == nillen(m3) == 0// true true
          // nil 賦值報錯
          // 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 不存在的情況下,也是不報錯的。而是返回對應類型的零值。

          刪除元素:

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

          獲取長度:

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

          判斷鍵是否存在:

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

          和 Python 對比起來看,這個用起來就很爽。

          遍歷:

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

          引用類型

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

          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)體是一種聚合類型,包含零個或多個任意類型的命名變量,每個變量叫做結(jié)構(gòu)體的成員。

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

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

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

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

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

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

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

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

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

          未初始化的字段會賦值相應類型的零值。

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

          使用點號 . 來訪問和賦值成員變量。

          // 訪問結(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)定義一個 user 結(jié)構(gòu)體了,假設我們再定義兩個結(jié)構(gòu)體 adminleader,如下:

          type admin struct {
              name    string
              age     int
              isAdmin bool
          }

          type leader struct {
              name     string
              age      int
              isLeader bool
          }

          那么問題就來了,有兩個字段 nameage 被重復定義了多次。

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

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

          type admin struct {
              u       user
              isAdmin bool
          }

          type leader struct {
              u        user
              isLeader bool
          }

          代碼看起來簡潔了很多。

          匿名成員

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

          // 結(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

          這個時候就需要匿名成員登場了,不指定名稱,只指定類型。

          type admin1 struct {
              user
              isAdmin bool
          }

          通過這種方式可以省略掉中間變量,直接訪問我們需要的成員變量。

          // 匿名成員
          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ù)類型。雖然篇幅不長,但基本操作也都包括,寫代碼肯定是沒有問題的。更底層的原理和更靈活的用法就需要大家自己去探索和發(fā)現(xiàn)了。

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

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

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

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


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

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

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

          Go 專欄文章列表:

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

          2. Go 專欄 | 變量和常量的聲明與賦值

          3. Go 專欄|基礎(chǔ)數(shù)據(jù)類型:整數(shù)、浮點數(shù)、復數(shù)、布爾值和字符串

          4. Go 專欄|復合數(shù)據(jù)類型:數(shù)組和切片 slice

          瀏覽 70
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  av网站在线看 | 91精品国产专区 | 豆花视频综合在线 | 三级av无码 | 黄网免费|