日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

js 调用另一个类的方法_一个隐藏在方法集和方法调用中且易被忽略的小细节

發布時間:2024/4/19 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 js 调用另一个类的方法_一个隐藏在方法集和方法调用中且易被忽略的小细节 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

來自公眾號:新世界雜貨鋪

作為一個長期從事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

總結

以上是生活随笔為你收集整理的js 调用另一个类的方法_一个隐藏在方法集和方法调用中且易被忽略的小细节的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。