Golang通用代码生成器Generis:支持泛型、自由格式宏、条件编译及HTML模板转换
Golang通用代码生成器Generis:支持泛型、自由格式宏、条件编译及HTML模板转换 在此通知大家,我刚发布了 Generis 的首个版本。这是一个轻量级代码预处理器,为 Go 语言添加了以下功能:
- 泛型
- 自由形式宏
- 条件编译
- HTML 模板
- Allman 风格转换
https://github.com/senselogic/GENERIS
其功能与 Ego 和 Genny 类似,但实现为类似 C++ 的自由形式预处理器。
对于喜欢纯粹惯用方式开发 Go 代码的人来说可能完全没用,显然我不是这样的人…
示例:
package main;
// -- IMPORTS
import (
"html"
"io"
"log"
"net/http"
"strconv"
);
// -- DEFINITIONS
#define DebugMode
#as true
// ~~
#define HttpPort
#as 8080
// ~~
#define WriteLine( {{text}} )
#as log.Println( {{text}} )
// ~~
#define local {{variable}} : {{type}};
#as var {{variable}} {{type}};
// ~~
#define DeclareStack( {{type}}, {{name}} )
#as
// -- TYPES
type {{name}}Stack struct
{
ElementArray []{{type}};
}
// -- INQUIRIES
func ( stack * {{name}}Stack ) IsEmpty(
) bool
{
return len( stack.ElementArray ) == 0;
}
// -- OPERATIONS
func ( stack * {{name}}Stack ) Push(
element {{type}}
)
{
stack.ElementArray = append( stack.ElementArray, element );
}
// ~~
func ( stack * {{name}}Stack ) Pop(
) {{type}}
{
local
element : {{type}};
element = stack.ElementArray[ len( stack.ElementArray ) - 1 ];
stack.ElementArray = stack.ElementArray[ : len( stack.ElementArray ) - 1 ];
return element;
}
#end
// ~~
#define DeclareStack( {{type}} )
#as DeclareStack( {{type}}, {{type:PascalCase}} )
// -- TYPES
DeclareStack( string )
DeclareStack( int32 )
// -- FUNCTIONS
func HandleRootPage(
response_writer http.ResponseWriter,
request * http.Request
)
{
local
boolean : bool;
local
natural : uint;
local
integer : int;
local
real : float64;
local
escaped_text,
text : string;
local
integer_stack : Int32Stack;
boolean = true;
natural = 10;
integer = 20;
real = 30.0;
text = "text";
escaped_text = "<escaped text/>";
integer_stack.Push( 10 );
integer_stack.Push( 20 );
integer_stack.Push( 30 );
#write response_writer
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title><%= request.URL.Path %></title>
</head>
<body>
<% if ( boolean ) { %>
<%= "URL : " + request.URL.Path %>
<br/>
<%@ natural %>
<%# integer %>
<%& real %>
<br/>
<%~ text %>
<%= escaped_text %>
<%= "<%% ignored %%>" %>
<%% ignored %%>
<% } %>
<br/>
Stack :
<br/>
<% for !integer_stack.IsEmpty() { %>
<%# integer_stack.Pop() %>
<% } %>
</body>
</html>
#end
}
// ~~
func main()
{
http.HandleFunc( "/", HandleRootPage );
#if DebugMode
WriteLine( "Listening on http://localhost:HttpPort" );
#end
log.Fatal(
http.ListenAndServe( ":HttpPort", nil )
);
}
更多关于Golang通用代码生成器Generis:支持泛型、自由格式宏、条件编译及HTML模板转换的实战教程也可以访问 https://www.itying.com/category-94-b0.html
无意冒犯,但既然已经有了Python,为什么还要写新的Python呢?
更多关于Golang通用代码生成器Generis:支持泛型、自由格式宏、条件编译及HTML模板转换的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我认为宏功能很不错。唯一不理解的是为什么要创建一个宏来将var改为local,并在语句末尾引入分号?这一点我实在无法理解
“local :” 宏只是自由格式宏的一个示例。其唯一目的是展示你可以使用自定义分隔符来定义宏 🙂
我使用分号不仅是出于个人偏好,还因为这有助于行连接器识别语句的结束位置。但如果你不使用 “–join” 选项来启用 Allman 风格缩进,就不需要任何分号,因为 Go 编译器会自动为你添加它们。
实际上我不得不使用Go来开发Web服务器,这让我非常怀念Crystal的诸多特性(泛型、宏、混入、模块等)。因此我开发了Generis,让这些特性也能在Go开发中使用。
我知道通过接口和反射,用符合Go语言习惯的代码就能实现任何功能。我完全没有批评那些坚持Go语言纯粹性、不想用泛型等特性"污染"代码的人。
但这些类似Crystal的附加特性虽然并非必需,对我来说却极其方便。更重要的是,它们还有个额外优势:生成的代码通常比基于接口/反射的等效实现运行速度要快得多。
所以我把Generis开源发布了,这样其他人也能使用它。不过我很清楚,大多数Go开发者可能对它不感兴趣,这我完全理解。
Generis 看起来是一个功能强大的 Go 代码预处理器,它通过宏和预处理指令扩展了 Go 语言的能力。以下是对示例代码中关键功能的解析:
1. 宏定义与替换
#define WriteLine( {{text}} )
#as log.Println( {{text}} )
#define local {{variable}} : {{type}};
#as var {{variable}} {{type}};
这些宏提供了语法糖,比如 WriteLine("hello") 会被替换为 log.Println("hello"),local count : int; 会被展开为 var count int。
2. 泛型栈实现
#define DeclareStack( {{type}}, {{name}} )
#as
type {{name}}Stack struct {
ElementArray []{{type}};
}
func ( stack * {{name}}Stack ) Push( element {{type}} ) {
stack.ElementArray = append( stack.ElementArray, element );
}
#end
DeclareStack( string )
DeclareStack( int32 )
通过宏生成类型安全的栈实现,DeclareStack(string) 会创建 StringStack 类型及其相关方法。
3. 条件编译
#define DebugMode
#as true
#if DebugMode
WriteLine( "Listening on http://localhost:HttpPort" );
#end
当 DebugMode 定义为 true 时,调试输出语句会被包含在最终代码中。
4. HTML 模板集成
#write response_writer
<!DOCTYPE html>
<html>
<body>
<% if ( boolean ) { %>
<%= "URL : " + request.URL.Path %>
<%@ natural %>
<% } %>
</body>
</html>
#end
这个特性允许在 Go 代码中直接嵌入 HTML 模板,支持条件判断、变量输出等模板语法。
5. 类型安全的栈操作
local integer_stack : Int32Stack;
integer_stack.Push( 10 );
integer_stack.Push( 20 );
<% for !integer_stack.IsEmpty() { %>
<%# integer_stack.Pop() %>
<% } %>
生成的栈类型提供类型安全的方法调用,在 HTML 模板中可以遍历栈内容。
Generis 通过预处理阶段将这些高级特性转换为标准的 Go 代码,为开发者提供了更灵活的代码组织方式,同时保持了编译时的类型安全。这种方案特别适合需要大量重复代码模式或希望在 Go 中使用更丰富元编程功能的场景。

