Go語言中隱式介面的衝突問題

來源:互聯網
上載者:User

標籤:

Go語言中隱式介面的衝突問題

Go語言中採用的是隱式介面, 只要滿足的介面的定義, 就可以當作介面使用.

比如內建的 error 介面:

type error struct {Error() string}

隱式介面的好處有很多. 但我個人覺得最主要的一點就是不需要再去畫祖宗八代的繼承關係圖了(松耦合).

但是隱式介面會帶來衝突問題.

簡單來說, 我也想定義一個自己的 MyError 介面, 裡面也有一個 Error() string 方法:

type MyError struct {Error() string}

但是我希望 MyError 介面 和 error 介面 是不同的類型 (不能相互轉換).

當然, 在 Go語言中 MyError 介面 和 error 介面 是等價的, 禁止 相互轉換 比較困難.

我們一般可以在 MyError 介面 中增加一個唯一的空方法 來迴避這個問題:

type MyError struct {Error() stringAssertMyError()}

方法 AssertMyError 只是為了區別 error 介面, 沒有其他用處.

這是 Protobuf 中 proto.Message 採用的方法:

// Message is implemented by generated protocol buffer messages.type Message interface {Reset()String() stringProtoMessage()}

產生的每個 Message 類型有個特殊的 ProtoMessage 空方法, 特別對應 proto.Message 介面.

當然, 如果有另一個介面剛好也有 ProtoMessage 方法, 還是有衝突的危險.

極端的做法是隨機產生一個 特別的 方法名, 比如用 UUID 做唯一名字.

但是, 公開的名字依然有被別人惡意覆蓋的危險(實際中不大可能).

更嚴格的做法是將這個用於區別介面的方法名定義為私人的方法. 比如 testing.TB:

type TB interface {Error(args ...interface{})Errorf(format string, args ...interface{})Fail()FailNow()Failed() boolFatal(args ...interface{})Fatalf(format string, args ...interface{})Log(args ...interface{})Logf(format string, args ...interface{})Skip(args ...interface{})SkipNow()Skipf(format string, args ...interface{})Skipped() bool// A private method to prevent users implementing the// interface and so future additions to it will not// violate Go 1 compatibility.private()}

private 不僅僅是私人方法, 而且必須是 testing 包內部定義的 private() 方法的類型才能匹配這個介面!

因此 testing.TB 介面是全域唯一的, 不會出現等價可互換的介面.

現在 testing.TB 保證了介面的唯一性, 但是如何在外部實現 這個介面呢(private()testing 包內部定義的)?

我們可以從 testing.TB 介面繼承這個 private() 方法:

package mainimport ("fmt""testing")type TB struct {testing.TB}func (p *TB) Fatal(args ...interface{}) {fmt.Println("TB.Fatal disabled!")}func main() {var tb testing.TB = new(TB)tb.Fatal("Hello, playground")}

play 地址: http://play.golang.org/p/tFB0fLwq9q

上面的代碼類比了顯式介面, 而且 testing.TB 介面永遠不用擔心有衝突的危險.

當然, 上面的代碼有過度提示的問題, 這和Go語言簡單的編程哲學是矛盾的.

Go語言中隱式介面的衝突問題

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.