1. 程式人生 > >go模板-程式碼生成器

go模板-程式碼生成器

能用程式去做的事,就不要用手,編寫自己的程式碼生成器就是用來解放你的雙手,替你做一些重複性的工作。 上篇帖子寫了模板的基礎 [go模板詳說](https://www.cnblogs.com/li-peng/p/12835425.html) ,有了基礎就要做點什麼東西,把所學到的東西應用起來才能更好的進步。於是用模板寫了一個程式碼生成器,用於把資料庫的錶轉換成`go`的`struct`,目前支援`MySQL`和`PostgreSQL`。這篇帖子寫實現的思路和一些具體的程式碼實現。 [Github地址: yggdrasill](https://github.com/lpxxn/yggdrasill) 看一下效果 ![](https://img2020.cnblogs.com/blog/342595/202005/342595-20200527122823443-218633248.gif) 大概的思路: * 就是得到資料庫下的所有的表資料。如果指定生成某幾個表,只需查一下是否存在相應的表。 * 根據表名得到列資訊,然後根據列的型別轉換成`go`的型別,如果有自定的型別要做特殊處理。 * 利用模板把表的資料轉換成結構體 ## 組織元資料 這裡的`元資料`也就是資料庫的表資訊,由於`MySQL`和`PostgreSQL`得到表和列資訊的實現方式不同,但是最終的資料結構是一致的,就寫了一個統一的介面來獲取元資料資訊。 ![](https://img2020.cnblogs.com/blog/342595/202005/342595-20200527122845284-162357862.png) ### MySQL `MySQL`從`information_schema.tables`得到一個數據庫下的所有表 ``` select table_name from information_schema.tables where table_schema = ? and table_type = 'base table'; ``` 如果只想查詢指寫的表,只需新增`table_name in`查詢條件就行。 表的列資訊從`information_schema.columns`獲取 ``` select column_name, is_nullable, if(column_type = 'tinyint(1)', 'boolean', data_type), column_type like '%unsigned%' from information_schema.columns where table_schema = ? and table_name = ? order by ordinal_position; ``` ### PostgreSQL `PostgreSQL`也是從`information_schema.tables`獲取表資訊,不同的是,不需要指定資料庫的名字,但`MySql`需要,感覺還是`PostgreSQL`更合理一些,因為在連線資料庫的`dsn`裡已經指定了要操作的`db`了 ``` select table_name from information_schema.tables where table_schema = 'public'; ``` 表的列資訊從`information_schema.columns`獲取 ``` select column_name, is_nullable, data_type, false from information_schema.columns where table_schema = 'public' and table_name = $1 order by ordinal_position; ``` ### 型別轉換 從資料庫裡獲取完表和列的資訊後,就要把資料庫的型別轉換成`go`相關的型別。 > 需要考慮的是是否有些型別要特殊處理,或自定義,特殊處理後的型別是否需要在`import`里加上具體的匯入。 方法`getGoType`把得到的資料庫型別進行對比,返回go的型別。 ![](https://img2020.cnblogs.com/blog/342595/202005/342595-20200527122906511-274649079.png) ## 模板 先看一下模板的程式碼,裡面的[知識點上篇帖子](https://www.cnblogs.com/li-peng/p/12835425.html)都有說過 ![](https://img2020.cnblogs.com/blog/342595/202005/342595-20200527122927425-618911205.png) 主要就是包名稱、是否有import、結構體資訊 `import`應該是會用到的,有用到時間型別就需要`import time`,還有前面說的,注意自定義的型別的匯入。 還有一點就是這個`Tag`,由於模板的功能還不夠豐富,就完全用方法去實現了 ![](https://img2020.cnblogs.com/blog/342595/202005/342595-20200527122937552-1513609168.png) 看一下生成的效果 ![](https://img2020.cnblogs.com/blog/342595/202005/342595-20200527122952509-1119254850.png) 也可以根據你的業務對這個庫進行擴充套件,由於專案不讓用`orm`完全手寫`sql`,我就根據自己的業務進行了擴充套件,把`dao`層的也實現了。 ![](https://img2020.cnblogs.com/blog/342595/202005/342595-20200527123001690-21833081.png) 一定要用模板實現麼?當然不是,可以用你喜歡的方式去實現,只是正好閱讀了模板的官方文件,就用他做了實現。 [Github地址: yggdrasill](https://github.com/lpxxn/yggd