等不及 go 泛型釋出,我先實現了(類似 C++ 的 template)
https://github.com/PioneerIncubator/betterGo 這個專案就是我帶著一位師弟實現的,有興趣的同學一起開發哈~
betterGo
Better Go implement parts that I think Golang missed
Real Generic
Provide the real interface{} to you so that you can use it in your code. Before deployment, just use translator to generate specify type code, in which way will not affect your performance.
Here are all generic functions:
- enum.Reduce
- enum.Map
Implementation
Use go ast to analyse your code where using generic functions, generate specify function for your types and replace your original call.
What I actually do
I do this shit for you :P
betterGo
Join Us
Background
現在的 Go 語言不支援泛型(像 C++ 中的 template、Java 中的 interface)
目前,為實現泛型的需求,在 Go 語言中往往有如下幾種方式1:
- Interface (with method) 優點:無需三方庫,程式碼乾淨而且通用。 缺點:需要一些額外的程式碼量,以及也許沒那麼誇張的執行時開銷。
- Use type assertions 優點:無需三方庫,程式碼乾淨。 缺點:需要執行型別斷言,介面轉換的執行時開銷,沒有編譯時型別檢查。
- Reflection 優點:乾淨 缺點:相當大的執行時開銷,沒有編譯時型別檢查。
- Code generation 優點:非常乾淨的程式碼 (取決工具),編譯時型別檢查(有些工具甚至允許編寫針對通用程式碼模板的測試),沒有執行時開銷。 缺點:構建需要第三方工具,如果一個模板為不同的目標型別多次例項化,編譯後二進位制檔案較大。
betterGo
就是通過code generation
來實現泛型
如何使用
想用一下 betterGo 的,可以看看這個例子哈:
克隆程式碼後,我們做了測試例子,程式碼就是test/map/map.go
,你正常用interface{}
的函式就是Enum.Map
這樣子用。
然後想生成具體型別的函式,就執行這行命令:go run main.go -w -f test/map/map.go
然後你發現 test/map/map.go
改變了,Enum.Map
變成了: enum.MapOriginFn(origin, fn)
然後你看專案底下生成了: utils/enum/map.go
,就是具體型別的函式
參與專案
關於參與專案的話,可以直接看程式碼,然後看到 ast 相關的包,就簡單進去看看,猜猜什麼意思,應該就可以理解這個專案以及程式碼了。
如果想從理論出發的話,可以簡單看看這本書:https://github.com/chai2010/go-ast-book ,其實他也就是把 ast 包裡的程式碼簡單講講。
想參與具體開發的話,又沒有想改進的地方,可以看看 issue 列表哈:https://github.com/PioneerIncubator/betterGo/issues
技術思路
匯入需要操作的檔案,可以是檔案/目錄
通過 AST 進行語法分析
AST 能分析出每條語句的性質,如:
-
GenDecl
(一般宣告):包括 import、常量宣告、變數宣告、型別宣告 -
AssignStmt
(賦值語句):包括賦值語句和短的變數宣告 (a := 1) -
FuncDecl
(函式宣告) -
TypeAssertExpr
(型別斷言) -
CallExpr
(函式呼叫語句)
當分析到包含變數的值/型別的語句時 (
AssignStmt
、FuncDecl
) 會對變數的值和型別進行記錄,並建立二者之間的對映關係,以便於在後續環節中能夠通過變數名獲取變數的型別當發現函式呼叫語句 (
CallExpr
) 時,會檢查該函式是否為我們提供的函式,如果是,則通過上一步中記錄的引數名對應的型別生成專門處理該型別的一份程式碼,並儲存到指定路徑下(如果之前已經生成過相同型別的程式碼則不重複生成)將原始碼中的原來的函式呼叫語句替換成新的函式呼叫語句,使其呼叫上一步中新生成的函式,並更新 import 的包
Reference
- [1] Go 有什麼泛型的實現方法? - 達的回答 - 知乎- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 支援泛型的Go語言1.18釋出泛型Go
- go如何實現類似java的動態代理GoJava
- C++ 簡單實現陣列類泛型程式設計示例C++陣列泛型程式設計
- 用Java 19實現類似Go併發 - mccueJavaGo
- Hibernate 泛型實現 dao 層的基類泛型
- 泛型最佳實踐:Go泛型設計者教你如何用泛型泛型Go
- Go 泛型Go泛型
- Go 泛型變更:約束太醜了,先移動到 x/exp 做實驗性功能Go泛型
- 01 . Go之從零實現Web框架(類似Gin)GoWeb框架
- go-easy-utils 2.0 正式釋出,全面支援泛型和anyGo泛型
- Go 泛型之泛型約束Go泛型
- 泛型類及系統中常用的泛型類泛型
- 泛型類和泛型方法泛型
- 泛型類、泛型方法及泛型應用泛型
- C++ Templates (2.1 類别範本Stack的實現 Implementation of Class Template Stack)C++
- 簡單易懂的 Go 泛型使用和實現原理介紹Go泛型
- go泛型教程Go泛型
- TypeScript 泛型介面和泛型類TypeScript泛型
- Java泛型知識點:泛型類、泛型介面和泛型方法Java泛型
- Go 實現泛型展開以及展開時計算Go泛型
- 用 C++ 實現類似於 JAVA HttpServlet 的程式設計介面C++JavaHTTPServlet程式設計
- 用C++ Builder 實現類似ie位址列的ComboBox (轉)C++UI
- 泛型類、泛型方法、型別萬用字元的使用泛型型別字元
- JAVA泛型類Java泛型
- 有沒有類似上線釋出管理的工具
- PostgreSQL類似OracleMERGE功能的實現SQLOracle
- 我理解的 Java 泛型Java泛型
- go需要泛型的場景Go泛型
- Go 需要泛型的場景Go泛型
- LiveKit:使用Go與WebRTC實現類似Zoom高影片質量GoWebOOM
- 易優實現釋出時間顯示類似幾小時前、幾天前的效果
- 泛型類派生子類泛型
- go實現類似與spring的全域性上下文獲取getPrincipal()GoSpring
- 簡單實現類似Spring的Aop原理實現Spring
- [開源]愛釋出類似fir.im和蒲公英的App釋出平臺APP
- GO語言泛型程式設計實踐Go泛型程式設計
- Go 官方出品泛型教程:如何開始使用泛型Go泛型
- Go泛型基礎使用Go泛型