<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 經典入門系列 15:指針

          共 4343字,需瀏覽 9分鐘

           ·

          2020-12-17 02:15

          點擊上方藍色“Go語言中文網”關注,每天一起學 Go

          歡迎來到 Golang 系列教程的第 15 個教程。

          什么是指針?

          指針是一種存儲變量內存地址(Memory Address)的變量。

          指針示意圖

          如上圖所示,變量 b 的值為 156,而 b 的內存地址為 0x1040a124。變量 a 存儲了 b 的地址。我們就稱 a 指向了 b

          指針的聲明

          指針變量的類型為 *T,該指針指向一個 T 類型的變量。

          接下來我們寫點代碼。

          package?main

          import?(
          ????"fmt"
          )

          func?main()?{
          ????b?:=?255
          ????var?a?*int?=?&b
          ????fmt.Printf("Type?of?a?is?%T\n",?a)
          ????fmt.Println("address?of?b?is",?a)
          }

          在線運行程序[1]

          & 操作符用于獲取變量的地址。上面程序的第 9 行我們把 b 的地址賦值給 *int 類型的 a。我們稱 a 指向了 b。當我們打印 a 的值時,會打印出 b 的地址。程序將輸出:

          Type?of?a?is?*int
          address?of?b?is?0x1040a124

          由于 b 可能處于內存的任何位置,你應該會得到一個不同的地址。

          指針的零值(Zero Value)

          指針的零值是 nil

          package?main

          import?(
          ????"fmt"
          )

          func?main()?{
          ????a?:=?25
          ????var?b?*int
          ????if?b?==?nil?{
          ????????fmt.Println("b?is",?b)
          ????????b?=?&a
          ????????fmt.Println("b?after?initialization?is",?b)
          ????}
          }

          在線運行程序[2]

          上面的程序中,b 初始化為 nil,接著將 a 的地址賦值給 b。程序會輸出:

          b?is?
          b?after?initialisation?is?0x1040a124

          指針的解引用

          指針的解引用可以獲取指針所指向的變量的值。將 a 解引用的語法是 *a

          通過下面的代碼,可以看到如何使用解引用。

          package?main
          import?(
          ????"fmt"
          )

          func?main()?{
          ????b?:=?255
          ????a?:=?&b
          ????fmt.Println("address?of?b?is",?a)
          ????fmt.Println("value?of?b?is",?*a)
          }

          在線運行程序[3]

          在上面程序的第 10 行,我們將 a 解引用,并打印了它的值。不出所料,我們會打印出 b 的值。程序會輸出:

          address?of?b?is?0x1040a124
          value?of?b?is?255

          我們再編寫一個程序,用指針來修改 b 的值。

          package?main

          import?(
          ????"fmt"
          )

          func?main()?{
          ????b?:=?255
          ????a?:=?&b
          ????fmt.Println("address?of?b?is",?a)
          ????fmt.Println("value?of?b?is",?*a)
          ????*a++
          ????fmt.Println("new?value?of?b?is",?b)
          }

          在線運行程序[4]

          在上面程序的第 12 行中,我們把 a 指向的值加 1,由于 a 指向了 b,因此 b 的值也發(fā)生了同樣的改變。于是 b 的值變?yōu)?256。程序會輸出:

          address?of?b?is?0x1040a124
          value?of?b?is?255
          new?value?of?b?is?256

          向函數(shù)傳遞指針參數(shù)

          package?main

          import?(
          ????"fmt"
          )

          func?change(val?*int)?{
          ????*val?=?55
          }
          func?main()?{
          ????a?:=?58
          ????fmt.Println("value?of?a?before?function?call?is",a)
          ????b?:=?&a
          ????change(b)
          ????fmt.Println("value?of?a?after?function?call?is",?a)
          }

          在線運行程序[5]

          在上面程序中的第 14 行,我們向函數(shù) change 傳遞了指針變量 b,而 b 存儲了 a 的地址。程序的第 8 行在 change 函數(shù)內使用解引用,修改了 a 的值。該程序會輸出:

          value?of?a?before?function?call?is?58
          value?of?a?after?function?call?is?55

          不要向函數(shù)傳遞數(shù)組的指針,而應該使用切片

          假如我們想要在函數(shù)內修改一個數(shù)組,并希望調用函數(shù)的地方也能得到修改后的數(shù)組,一種解決方案是把一個指向數(shù)組的指針傳遞給這個函數(shù)。

          package?main

          import?(
          ????"fmt"
          )

          func?modify(arr?*[3]int)?{
          ????(*arr)[0]?=?90
          }

          func?main()?{
          ????a?:=?[3]int{89,?90,?91}
          ????modify(&a)
          ????fmt.Println(a)
          }

          在線運行程序[6]

          在上面程序的第 13 行中,我們將數(shù)組的地址傳遞給了 modify 函數(shù)。在第 8 行,我們在 modify 函數(shù)里把 arr 解引用,并將 90 賦值給這個數(shù)組的第一個元素。程序會輸出 [90 90 91]

          a[x](*a)[x] 的簡寫形式,因此上面代碼中的 (*arr)[0] 可以替換為 arr[0]。下面我們用簡寫形式重寫以上代碼。

          package?main

          import?(
          ????"fmt"
          )

          func?modify(arr?*[3]int)?{
          ????arr[0]?=?90
          }

          func?main()?{
          ????a?:=?[3]int{89,?90,?91}
          ????modify(&a)
          ????fmt.Println(a)
          }

          在線運行程序[7]

          該程序也會輸出 [90 90 91]

          這種方式向函數(shù)傳遞一個數(shù)組指針參數(shù),并在函數(shù)內修改數(shù)組。盡管它是有效的,但卻不是 Go 語言慣用的實現(xiàn)方式。我們最好使用切片[8]來處理。

          接下來我們用切片[9]來重寫之前的代碼。

          package?main

          import?(
          ????"fmt"
          )

          func?modify(sls?[]int)?{
          ????sls[0]?=?90
          }

          func?main()?{
          ????a?:=?[3]int{89,?90,?91}
          ????modify(a[:])
          ????fmt.Println(a)
          }

          在線運行程序[10]

          在上面程序的第 13 行,我們將一個切片傳遞給了 modify 函數(shù)。在 modify 函數(shù)中,我們把切片的第一個元素修改為 90。程序也會輸出 [90 90 91]所以別再傳遞數(shù)組指針了,而是使用切片吧。上面的代碼更加簡潔,也更符合 Go 語言的習慣。

          Go 不支持指針運算

          Go 并不支持其他語言(例如 C)中的指針運算。

          package?main

          func?main()?{
          ????b?:=?[...]int{109,?110,?111}
          ????p?:=?&b
          ????p++
          }

          在線運行程序[11]

          上面的程序會拋出編譯錯誤:main.go:6: invalid operation: p++ (non-numeric type *[3]int)

          我在 github[12] 上創(chuàng)建了一個程序,涵蓋了所有我們討論過的內容。

          關于指針的介紹到此結束。祝您愉快。

          上一教程 - 字符串

          下一教程 - 結構體[13]


          via: https://golangbot.com/pointers/

          作者:Nick Coghlan[14]譯者:Noluye[15]校對:polaris1119[16]

          本文由 GCTT[17] 原創(chuàng)編譯,Go 中文網[18] 榮譽推出

          參考資料

          [1]

          在線運行程序: https://play.golang.org/p/A4vmlgxAy8

          [2]

          在線運行程序: https://play.golang.org/p/yAeGhzgQE1

          [3]

          在線運行程序: https://play.golang.org/p/m5pNbgFwbM

          [4]

          在線運行程序: https://play.golang.org/p/cdmvlpBNmb

          [5]

          在線運行程序: https://play.golang.org/p/3n2nHRJJqn

          [6]

          在線運行程序: https://play.golang.org/p/lOIznCbcvs

          [7]

          在線運行程序: https://play.golang.org/p/k7YR0EUE1G

          [8]

          切片: https://golangbot.com/arrays-and-slices/

          [9]

          切片: https://golangbot.com/arrays-and-slices/

          [10]

          在線運行程序: https://play.golang.org/p/rRvbvuI67W

          [11]

          在線運行程序: https://play.golang.org/p/WRaj4pkqRD

          [12]

          github: https://github.com/golangbot/pointers

          [13]

          結構體: https://studygolang.com/articles/12263

          [14]

          Nick Coghlan: https://golangbot.com/about/

          [15]

          Noluye: https://github.com/Noluye

          [16]

          polaris1119: https://github.com/polaris1119

          [17]

          GCTT: https://github.com/studygolang/GCTT

          [18]

          Go 中文網: https://studygolang.com/



          推薦閱讀


          福利

          我為大家整理了一份從入門到進階的Go學習資料禮包,包含學習建議:入門看什么,進階看什么。關注公眾號 「polarisxu」,回復 ebook 獲取;還可以回復「進群」,和數(shù)萬 Gopher 交流學習。

          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  秋霞网址| 九九手机看片 | 白天操夜夜操 | 18av在线播放 | 九九综合在线资源伦理 |