<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在review 一些程式碼中,發現經常某個型別定義的方法,其接收者既有值型別,又有指標型別,然後 Goland 就有提示: Struct Person has methods on both value and pointer receivers. Such usage is not recommended by the Go Documentation.
一般來講,這個提示對程式碼的執行並不會產生什麼問題。只不過對於有輕微 “程式碼潔癖” 的人來講,體感不好,就一定想要改統一。
當然,我並不是想講要統一的問題,前面說這麼多廢話,只是為了鋪墊一下引出本文的內容:Go中的值接收者與指標接收者有什麼關係與區別,該怎麼選?
在繼續講下去之前,我們得先明確,Go 裡邊能夠定義方法的必須是自定義型別,而不能是系統內建型別,比如 int、string 這種是不可以為其新增方法的。
那麼當我們定義了一個自定義型別,可以為其新增方法,先上程式碼:
package main import "fmt" type Person struct { name string age int } // 值針接收者 func (p Person) GetName() string { return p.name } // 指標接收者 func (p *Person) GetAge() int { return p.age } func main() { // 定義了一個【值型別】 t := Person{ name: "DaYu", age: int(28), } // 呼叫值方法 fmt.Println(t.GetName()) // 呼叫指標方法 fmt.Println(t.GetAge()) } -----執行結果------- study/demo01/client go run * DaYu 28
從使用過程看,值型別的變數,可以呼叫該型別的值接收者方法,也可以呼叫指標接收者方法。
反之,我們可以定義一個指標型別,然後看看呼叫結果:
package main import "fmt" type Person struct { name string age int } func (p *Person) GetName() string { return p.name } func (p Person) GetAge() int { return p.age } func main() { // 注意,其它地方都沒有改,只是這裡改變了型別 t := &Person{ name: "DaYu", age: int(28), } fmt.Println(t.GetName()) fmt.Println(t.GetAge()) } -----執行結果------- study/demo01/client go run * DaYu 28
這段程式碼告訴我們,指標型別的變數,可以呼叫該型別的值接收者方法,也可以呼叫指標接收者方法。
是不是特別有意思?
看起來好像兩者對等的,並沒有差別。那麼二者真的沒有差別嗎?只是一種表達形式上的差異?其實不然,如果引入介面型別後,我們再來看看。
package main // 新增的介面 type Animal interface { GetName() string GetAge() int } type Person struct { name string age int } func (p *Person) GetName() string { return p.name } func (p Person) GetAge() int { return p.age } func main() { // 定義的介面變數 var ani Animal // person 實現了 Animal 介面,賦值給了 ani 變數 // 但是,這裡編譯會通不過,錯誤如下: // Cannot use 'Person{ name: "DaYu", age: int(28), }' (type Person) as the type Animal Type does not implement 'Animal' as the 'GetName' method has a pointer receiver ani = Person{ name: "DaYu", age: int(28), } ani.GetName() ani.GetAge() }
為什麼會報錯呢? 錯誤提醒很明顯了:Person 沒有實現 Animal 的 GetName 方法。因為在上面的程式碼中,我們實現 GetName 方法的是 (*Person) 型別。
但是為什麼 GetAge 方法不報錯呢? 那是因為 Go 裡邊對於 (Type)Method 的方法,會自動讓他擁有 (*Type)Method 方法的能力。
至於為什麼不也隱式申明一個 (Type)Method ,我覺得有一個原因是,我們一般採用指標接收者時,方法內部改變的值,接收者本身也會改變,那麼此時如果隱式有這樣一個申明,外部使用值型別時,這個改變就不會生效,語意上就會非常奇怪。
從使用表現上看,指標接收者在方法內部的改變,會體現到其本身。但這並不是決定我們要不要用指標接收者的唯一理由! 最重要的還是看接收者要不要全域性共用一個實體,其次某些場景下,如果接收者本身太大,拷貝成本很高,也應該使用指標接收者。
回到檔案開篇的問題,為什麼不建議值接收者、指標接收者混用,主要還是在於語意不夠清晰,存在潛在理解成本的問題。
以上就是Go方法接收者值接收者與指標接收者詳解的詳細內容,更多關於Go方法值接收者指標接收者的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45