昨天到公司看到有人在群裡把go跟java的interface做比較,提出go宣稱的“非侵入式”好像也沒那麼好用,甚至跟java差不多。但實際上go語言的接口設計并不隻是文法本身,也包含了開發流程跟思維方式在裡面,下面把當時在群裡的回答整理一下放出來。
其實可以這樣來了解:
Java語言的開發風格是設計先行,即先定義規範,然後去挨個實作(就是先定義有什麼方法,然後再寫出來方法體)。
而go語言是“先做再說”,即先把功能實作,然後抽取出接口。
在實際開發流程中,早先的從文檔到代碼的流程,确實Java更符合。但是開發流程本身也是在發展的,比如後來居上的靈活流程就讓Java出現了雪崩的感覺(給interface加個東西,所有聲明implement該interface的都會報錯)。但是go就比較貼合這種流程,首先出現的是具體幹活的實體,實體多了才抽象出的接口,有了接口之後新寫的代碼可以使用interface作為參數類型,同時不會導緻原有代碼編譯失敗。這就允許開發者随意在未來的任何時間來重構代碼,或者不做任何修改,這才是“非侵入式”。
群裡當時那問題,舉例說定義了“插座”這個接口,定義“微波爐”和“空調”去實作這個接口,後來“插座”多了個“開關”方法,就導緻“微波爐”和“空調”也需要實作“開關”這個方法。我當時覺得他說的插座應該是想說能插電的裝置,于是在回答的時候用的是“電器”,對這個問題我是這麼回答的:
然後說下你的問題,在java中可能是先在設計階段,就定好了插座、微波爐、空調及他們之間的關系。後面設計變更加上了“開關”這個方法。但是go語言的風格是用什麼就做什麼,需要有東西加熱食品,就先做微波爐,需要有東西調節氣溫,就做出個空調。然後發現公共部分可以抽象出來一個“電器”接口,于是就有了這個interface。這一過程的任何階段,在go語言風格中都是編譯通過的,至于是否需要把原來以空調或微波爐為參數的func重構為以電器,就可以根據實際情況來了。然後“開關”這個方法也不是憑空出現在接口中的,而是在實際開發中,發現微波爐需要有“開關”功能,然後給微波爐實作了;然後發現空調也用到了“開關”功能也加上了,這個時候開始思考是不是“電器”都需要“開關”呢,于是電器這個接口就有了“開關”。
實際上人不可能一開始就把東西設計的很完美,是以先定義後實作的路子走下來就是,設計變更帶來的改動很大。而go這種先實作好實體,然後抽象出接口的思想,就更貼合實際。是以說go語言的interface設計不隻是文法,更是一種思維方式。實際上Rob Pike在GoogleIO上講go語言對并發支援的由來,就是“real world”本身就是很多事情在各自獨立互不影響的進行着。
略表拙見,如果有大佬路過發現哪裡不妥的感謝指正!