安卓一个方法多处调用_一个隐藏在方法集和方法调用中且易被忽略的小细节
作為一個長期從事Go語言開發的程序猿,筆者不敢說自己是老油條但也勉強算一個小油條。然而就在今天,筆者研究TLS/SSL握手源碼的時候,突然靈光一閃,想到了一個和自己認知不符的現象,于是趕緊寫了一個例子驗證一番,結果當頭一棒直到碼這篇文章時依舊懵逼。
話不多說,上錘!
不好意思,不是這個錘,是下面這個:
type set interface {set1(s string)set2(s string) } type test struct {s string } func (t *test) set1(s string) {t.s = s } func (t test) set2(s string) {t.s = s } func main() {var (t1 testt2 = new(test))t1.set1("1")fmt.Print(t1.s)t1.set2("2")fmt.Print(t1.s)t2.set1("3")fmt.Print(t2.s)t2.set2("4")fmt.Print(t2.s)fmt.Print(" ")_, ok1 := (interface{}(t1)).(set)_, ok2 := (interface{}(t2)).(set)fmt.Println(ok1, ok2) }正確答案筆者就不直接公布了,請各位讀者耐心在后文尋找答案。
方法集
根據golang官方文檔知道,一個類型有一個與之關聯的方法集。接口類型的方法集是接口中定義的方法。
官方文檔中特別提到,類型T的方法集包含用T聲明為Receiver的所有方法,而指針類型*T的方法集包含用T和*T聲明的所有方法。
此時,我們回到上面的例子可以很明顯的知道下面這段代碼輸出為false true。
_, ok1 := (interface{}(t1)).(set) _, ok2 := (interface{}(t2)).(set) fmt.Println(ok1, ok2)T類型的方法集不包含*T類型的方法集,因此t1無法轉為set接口類型。
事實上,根據這部分官方文檔筆者更加疑惑了,因為上述例子可以正常運行,而且類型為test的變量調用了(*test).set1方法。抱著這樣的疑惑筆者瘋狂谷狗,最后在stackoverflow的指導下發現了這種情況和方法調用有關。
這里特別感謝一下谷狗和stackoverflow。
方法調用
方法調用筆者在這里僅說明和本篇相關的內容,其他細節相信各位讀者都已經了然于胸。
下面,先看看官方文檔原文:
A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()簡單來說,如果x可尋址,且&x的方法集包含m,則x.m()是(&x).m的縮寫。這樣前面的例子能夠正常運行也在情理之中了。
因此,前面例子的最終輸出結果是:1133 false true。
如果讀者對結構體中的值未發生改變有疑惑,請參考筆者的這篇文章——為什么go中的receiver name不推薦使用this或者self。
你以為你都懂了
寫完前面的方法集和方法調用筆者細細思考一番,確認沒有其他遺漏的細節,于是放心的上了個廁所。結果廁所還沒上完,立馬想到一個問題(額外多扯一句,筆者經常在上廁所的時候找到靈感,這可能就是勞逸結合的最佳實踐吧):
type los stringfunc (s los) p1() {fmt.Println(s) }func (s *los) p2() {fmt.Println(s) }func main() {var s1 los = "1111"var s2 *los = &s1const s3 los = "3333"s1.p1()s1.p2()s2.p1()s2.p2()s3.p1()s3.p2() }如果你對上面的代碼沒有任何疑問且認為上述代碼能夠正常運行,那只能說明你對本文的閱讀還不夠認真。
我們先看看上述代碼在vscode中的報錯。
前面介紹方法調用時,如果x可尋址,則x可以調用&x的類型的方法集。上述代碼s3是常量,是不可以尋址的,因此無法調用(*los).p2方法。
以上,就是筆者曾經忽略的細節,現在回過頭來看一看倒也充滿了樂趣。
彩蛋
本篇是研究TLS/SSL握手流程的副產品,因為TLS/SSL握手流程筆者還在整理中,故這篇文章先行一步給個預告,下一期TLS/SSL握手流程敬請期待。
最后,衷心希望本文能夠對各位讀者有一定的幫助。
注: 1. 寫本文時, 筆者所用go版本為: go1.15.2 2. 文章中所用完整例子:https://github.com/Isites/go-coder/blob/master/receiver/main.go參考
https://golang.org/ref/spec#Method_sets
https://golang.org/ref/spec#Calls
總結
以上是生活随笔為你收集整理的安卓一个方法多处调用_一个隐藏在方法集和方法调用中且易被忽略的小细节的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql数据清洗_mysql数据库如何
- 下一篇: java异步调用第三方接口_Java调用