go_macro is a simple, lightweight go macro implementation written by Rust. It provides macro definition and invocation feature for go. You can use the macro as Generics implementation, hyper-function, or anything you can do with macros(as you like). The macro is inspired by the C preprocessor.
Download the command-line binary go-macro, and then run:
go-macro --source <go file or directory> --target <target directory> [--format]The program would translate all input go files into target directory,
and the --format option represents whether to format the code by gofmt(binary required).
The default --source and --default option are ./ and ./go-target.
Then you can run cd <target directory> && go build to build your go program.
See the example in example directory.
You can define a macro by using #define, and ends a definition by using #enddef:
#define MAX_CPU_NUM
4
#enddefor with arguments:
#define Wrapper(T)
struct{ Inner T }
#enddefThe macro can be used anywhere, just like a variable or a function:
const ProcessorNum = MAX_CPU_NUMwill be translated to:
const ProcessorNum = 4and
var wrapper = Wrapper(int){ Inner: 0 }will be translated to
var wrapper = struct{ Inner int }{ Inner: 0 }You can include macros in other files by using #include "<file/directory>":
#include "./macros"All macros in "./macros" will be imported.
NOTE: the program would panic if cross reference happens.
There are two builtin macros: concat/str.
- The
concatmacro is to concat the given arguments; - The
strmacro converts input as astring;
see the example below:
#define NUM
str(3)
#enddef
func main() {
// here the i shoud be "3"
var i = concat(N, U, M)
}The macro can be invoked recursively:
#define TYPE
int64
#enddef
#define add
func(x, y TYPE) TYPE {
return x + y
}
#enddef
func main() {
var _ = add(1, 2)
}will be translate to
func main() {
var _ = func(x, y int64) int64 {
return x + y
}(1, 2)
}The code below would cause a recursion limit error:
#define name
name
#enddefthe recursion limit is 32 by default.
Let's make Generics possible by using macro:
#define sort(T)
func(list []T) {
// sort implement here
}
#enddef
func main() {
var list = []byte("string")
sort(byte)(list)
// would be "ginrst"
fmt.Println(string(list))
}- Add command
#include; - Add more commands like
#if,#for; - Use LinkedList instead of Vec for better performance;
- Maybe it is necessary to write more comments?