<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 專欄|說說方法

          共 3422字,需瀏覽 7分鐘

           ·

          2021-08-31 21:14

          最近又搬家了,已經(jīng)記不清這是第幾次搬家了。搬到了公司附近,走路十分鐘,以后加班可方便了。

          這一篇來說一說方法,方法可以看作是某種特定類型的函數(shù),是 Go 面向?qū)ο缶幊痰牡谝徊健S煤梅椒ǎ邆涿嫦驅(qū)ο缶幊趟枷胧顷P(guān)鍵。

          聲明

          方法的聲明和函數(shù)類似,他們的區(qū)別是:方法在定義的時(shí)候,會(huì)在 func 和方法名之間增加一個(gè)參數(shù),這個(gè)參數(shù)就是接收者,這樣我們定義的這個(gè)方法就和接收者綁定在了一起,稱之為這個(gè)接收者的方法。

          type Person struct {
              name string
          }

          func (p Person) String() string {
              return "person name is " + p.name
          }

          func 和方法名之間增加的參數(shù) (p Person)  就是接收者。現(xiàn)在我們說,類型 Person 有了一個(gè) String 方法。

          調(diào)用方法非常簡(jiǎn)單,使用類型的變量和 . 操作符進(jìn)行調(diào)用即可。

          p := Person{name: "zhangsan"}

          // 調(diào)用方法
          fmt.Println(p.String()) // person name is zhangsan

          值語義和引用語義

          Go 語言里有兩種類型的接收者:值接收者和指針接收者。

          使用值類型接收者定義的方法,在調(diào)用的時(shí)候,使用的其實(shí)是值接收者的一個(gè)副本,所以對(duì)該值的任何操作,不會(huì)影響原來的類型變量。

          func main() {
              p := Person{name: "zhangsan"}

              // 調(diào)用方法
              fmt.Println(p.String()) // person name is zhangsan

              // 值接收者
              p.Modify()
              fmt.Println(p.String()) // person name is zhangsan
          }

          // 值接收者
          func (p Person) Modify() {
              p.name = "lisi"
          }

          接下來再看一下使用指針接收者的效果:

          func main() {
              p := Person{name: "zhangsan"}

              // 調(diào)用方法
              fmt.Println(p.String()) // person name is zhangsan

              // 指針接收者
              p.ModifyP()
              fmt.Println(p.String()) // person name is lisi
          }

          // 指針接收者
          func (p *Person) ModifyP() {
              p.name = "lisi"
          }

          可以看到,改變了原始值,其實(shí)這一點(diǎn)和函數(shù)傳參是一樣的。

          有沒有發(fā)現(xiàn),我們?cè)谡{(diào)用指針接收者方法的時(shí)候,使用的也是一個(gè)值的變量,并不是一個(gè)指針,正常來說應(yīng)該這么寫:

          (&p).ModifyP()
          fmt.Println(p.String())

          同樣的,如果是一個(gè)值接收者的方法,使用指針也是可以調(diào)用的:

          (&p).Modify()
          fmt.Println(p.String())

          原因是編譯器幫我們自動(dòng)轉(zhuǎn)義了,這一點(diǎn)大大的方便了我們開發(fā)者。

          方法變量和表達(dá)式

          上文中已經(jīng)介紹了一種調(diào)用方法,直接使用 . 操作符,比如:p.String()

          接下來再介紹兩種調(diào)用方法:

          方法變量

          p.Add 可以賦值給一個(gè)方法變量,它相當(dāng)于一個(gè)函數(shù),把方法綁定到一個(gè)接收者上。然后函數(shù)只需要提供實(shí)參而不需要提供接收者即可調(diào)用。

          type Point struct {
              x, y int
          }

          func main() {
              // 方法變量
              p1 := Point{12}
              q1 := Point{34}
              f := p1.Add
              fmt.Println(f(q1)) // {4 6}
          }

          func (p Point) Add(q Point) Point {
              return Point{p.x + q.x, p.y + q.y}
          }

          方法表達(dá)式

          方法表達(dá)式寫成 T.f 或者 (*T).f,其中 T 是類型,是一種函數(shù)變量。

          因?yàn)檎{(diào)用方法必須要提供接收者,這種方法相當(dāng)于把接收者替換成了函數(shù)的第一個(gè)形參,因此它可以像函數(shù)一樣調(diào)用。

          // 方法表達(dá)式
          f1 := Point.Add
          fmt.Println(f1(p1, q1)) // {4 6}

          總結(jié)

          本文主要學(xué)習(xí)了 Go 的方法,方法的聲明和函數(shù)類似,他們的區(qū)別是:方法在定義的時(shí)候,會(huì)在 func 和方法名之間增加一個(gè)參數(shù),這個(gè)參數(shù)就是接收者。

          接收者有兩種類型:值接收者和指針接收者。不管是使用值接收者,還是指針接收者,一定要搞清楚類型的本質(zhì):對(duì)類型進(jìn)行操作的時(shí)候,是要改變當(dāng)前值,還是要?jiǎng)?chuàng)建一個(gè)新值進(jìn)行返回?這些就可以決定我們是采用值傳遞,還是指針傳遞。

          最后就是方法的調(diào)用,可以直接使用 . 操作符調(diào)用,還可以使用方法變量和方法表達(dá)式。

          只有基于面向?qū)ο缶幊趟枷耄拍苁褂煤梅椒āT诤竺嬉獙W(xué)習(xí)的接口中,方法還有更多的應(yīng)用。


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

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

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

          Go 專欄文章列表:

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  亚洲欧洲视频 | 秘 黄 视频免费看 | 成人精品一区二区三区 | 国产精品扒开腿做爽爽爽网站免费 | 国精品无码一区二区三区在线 |