Go语言有很多工具, goimports用于package的自动导入或者删除, golint用于检查源码中不符合Go coding style的地方, 比如全名,注释等. 还有其它工具如gorename, guru等工具. 作为工具它们都是使用go语言(查看)开发的, 这些工具都有一个共同点就是: 读取源代码, 分析源代码, 修改或生成新代码.

简述

很多编程语言/库/框架等都能生成代码, 比如使用rails, 可以轻松地new一个project出来, 生成项目基本代码, 我们称其为boilerplate, 或者template, 这已经习以为常了. 像ruby的动态语言通常能在运行时生成代码, 我们称之为meta programming(元编程), 比如rails的resources可以生成restful的router出来.因为是运行时动态生成, 因此可能会遇到exception, 以及性能方面有所损失.

像elixir这种编程语言的macro则比ruby的元编程方面向"前"一步, 它在编译期生成代码, 而不在运行时生成, 好处是可以生成大量的代码而对性能几乎没有太大影响. 像phoenix框架的router查看部分, 则通过macro生成大量的函数, 利用BEAM的pattern matching机制高效路由.elixir的macro是写在源代码里的, 而Go则可以分离.

Go语言可以通过reflect包同样做到ruby的运行时生成代码(比如创建对象), 但更强大的一点是, 它通过读取源码, 再修改源码, 生成新的代码.我们可以将这个过程单独写作一个工具, 这个工具可以适用于不同的项目.

例子

stringer

package game

//go:generate stringer -type=GameStatus
// 注意//与go:generate字符之间不能有空格
// GameStatus 表示比赛的状态
type GameStatus int const (
Unvalid GameStatus = iota
ValidFailed
Valid
Register
Start
Running
End
)

运行 go generate 会生成gamestatus_string.go文件, 并且实现了Stringer接口.

同样的例子在gRPC中也出现过code, 生成的string.正如Rob Pike所说:

let the mechine do the work.source

gen_columns

很多项目在使用数据库时, 通过tag指定数据库里的字段名字, 在写SQL时, 又只能通过字符串来表示字段名, 因此如果某一个字段名修改时, 则意味着涉及到此字段的SQL都面临着修改, 而我们希望只需要修改一个地方.

有一个结构作为数据库表结构如下:

type User struct {
ID int `json:"id" bson:"id"`
Name string `json:"name" bson:"name"`
}

当使用这个model里的字段进行sql查询时, 通常使用:

map[string]interface{}{
"id":123456,
}

作为查询条件, 如果当字段名更改时, 不得不修改这个map里的key值
如果能够自动生成一个结构体, 用于表示这些column name值, 那么只需修改一处:

map[string]interface{}{
UserColumns.ID: 123456
}

使用方法

gen_columns -tag="bson" -path="./models/user.go"

会生成一个独立的文件, 里面的内容为:

package models

type _UserColumn struct {
ID string
Name string
} var UserColumns _UserColumn func init() {
UserColumns.ID = "id"
UserColumns.Name = "name" }

总结
gen_columns是自己在项目中遇到问题所给出的解决办法, 第一版本是通过reflect做的, 总共需要好几个步骤; 使用ast做就只需在编译时多加一个go generate, 而这命令基本上可以集成在build的脚本里, 因此不需要再额外担心代码生成的问题.
让我们用Go创造更多生成代码的工具吧.

  

其它例子 

  • impl 指定一个接口, 生成接口所需方法
  • goa 一套用于写web service的DSL

Go语言AST尝试的更多相关文章

  1. golang(gin框架),基于RESTFUL的跨语言远程通信尝试

    golang(gin框架),基于RESTFUL的跨语言远程通信尝试 背景: 在今年的项目实训过程中,遇到了这样的问题: 企业老师讲课实用的技术栈是Java springboot. 实训实际给我们讲课以 ...

  2. 中文编程语言之Z语言初尝试: ZLOGO 4

    原文: https://zhuanlan.zhihu.com/p/31505895. 作者为本人. @TKT2016 开发的Z语言(ZLOGO是它的一个部分)是本人至今看到的唯一一个仍活跃开发的开源且 ...

  3. 2017-11-28 中文编程语言之Z语言初尝试: ZLOGO 4

    "中文编程"知乎专栏原文. 作者为本人. @TKT2016 开发的Z语言(ZLOGO是它的一个部分)是本人至今看到的唯一一个仍活跃开发的开源且比较完整的中文编程语言项目. 它的源码 ...

  4. JVM 平台上的各种语言的开发指南

    JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...

  5. R语言编程艺术(3)R语言编程基础

    本文对应<R语言编程艺术> 第7章:R语言编程结构: 第9章:面向对象的编程: 第13章:调试 ============================================== ...

  6. 在linux操作系统上进行简单的C语言源码的gcc编译实验

    尝试在linux上用gcc 而非封装完好的codeblocks,vs等ide 来编译c和cpp源程序 首先查看我的gcc版本,我的是VM centos 自带的,没有的话得自行安装,安装上gcc就可以在 ...

  7. 初刷LeetCode的感受

    自从上个月进入实验室的云安全项目组后,因为要接触到实际的代码,在实验室博士的建议下我们项目组的硕士开始刷LeetCode练习编程能力,保持每周抽空刷几道算法题.虽然刷的不多,到现在一共只刷了不到30题 ...

  8. 流程控制 - PHP手册笔记

    脚本由语句构成,语句靠流程控制实现功能,这一节主要介绍了几个关键字的使用. elseif elseif和else if的行为完全一样,如果用冒号来定义if/elseif条件,那就不能用两个单词的els ...

  9. 编程的毛病——C++之父访谈

    原文见:http://www.technologyreview.com/InfoTech/17831/  翻译:xeon 11/29/2006 在20世纪的80年代和90年代,Bjarne Strou ...

随机推荐

  1. Python2.7 转义和正则匹配中文

    今天爬虫(新浪微博 个人信息页面)的时候遇到了转义和正则匹配中文出乱码的问题. 先给出要匹配的部分网页源代码如下: <span class=\"pt_title S_txt2\&quo ...

  2. MYSQL select ....outfile.....from.....

    select .... outfile  'file_path' fields terminate by '\t' lines terminate by '\r\n' from table_name; ...

  3. 【安装SQLserver2008R2 出现错误,临时类 result=1】

    去服务中,停止此  AliWorkbench Safe service 服务....玛德,千牛工作台.垃圾

  4. hdu 1536 S-Nim_求sg值模版

    题意:给你很n堆石头,k代表你有k种拿法,然后给出没堆石头的数量,求胜负 直接套用模版 找了好久之前写的代码贴上来 #include<iostream> #include<algor ...

  5. redhat 安装virtualbox

    1.在官网下载virtual for linux 包,链接地址:https://www.virtualbox.org/wiki/Linux_Downloads.根据需要下载对应镜像. 2.由于下载的包 ...

  6. C#中的反射原理及应用(转)

    反射的概述 反射的定义:审查元数据并收集关于它的类型信息的能力.元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等, ...

  7. C++ 顶层 const

    我的主力博客:半亩方塘 本文的主要參考来源来自于:C++ Primer 中文版(第 5 版) 第 57 面至第 58 面 1. 顶层 const 与底层 const 概念 我们知道,指针本身是一个对象 ...

  8. ios5和ios6横竖屏支持及ipad和iphone设备的判断

    ios5和ios6横竖屏支持及ipad和iphone设备的判断 判断是ipad还是iphone设备.此定义在PayViewControllerDemo-Prefix.pch 定义如下: #define ...

  9. 具体解释HTML中的window对象和document对象

    Window -- 代表浏览器中一个打开的窗体: 对象属性 window //窗体自身 window.self //引用本窗户window=window.self window.name //为窗体命 ...

  10. Android 多线程:使用Thread和Handler (从网络上获取图片)

    当一个程序第一次启动时,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分 ...