Skip to content

Instantly share code, notes, and snippets.

@dgrijalva
Created April 6, 2013 22:07
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dgrijalva/5327825 to your computer and use it in GitHub Desktop.
Save dgrijalva/5327825 to your computer and use it in GitHub Desktop.
Experimenting with code generation using `go/ast`. I wanted to see if it was practical to use compilable go code as a template for project generation. For example: if you wanted to be able to generate a falcore app from a template, what would that look like? If you could keep the template file looking like regular go source code (without templat…
package main
import (
"fmt"
"os"
"strings"
"go/parser"
"go/token"
"go/ast"
"go/printer"
)
func main(){
fs := token.NewFileSet()
file, err := parser.ParseFile(fs, "template.go", nil, 0)
if err != nil {
fmt.Println("Can't parse file", err)
}
file.Name.Name = "bar"
r := &Renamer{"Foo", "Bar"}
ast.Walk(r, file)
printer.Fprint(os.Stdout, fs, file)
}
type Renamer struct {
find string
replace string
}
func (r *Renamer) Visit(node ast.Node) (w ast.Visitor) {
if node != nil {
switch n := node.(type){
case *ast.FuncDecl:
if n.Recv != nil && n.Recv.List != nil && len(n.Recv.List) > 0 {
field := n.Recv.List[0]
typ := field.Type.(*ast.StarExpr).X.(*ast.Ident).Name
if typ == r.find {
field.Names[0].Name = strings.ToLower(r.replace[0:1])
}
}
case *ast.Ident:
if n.Name == r.find {
n.Name = r.replace
}
}
}
return r
}
package foo
import (
"net/http"
)
type Foo struct {
}
func (f *Foo) Method(req *http.Request) *http.Response {
_ = new(Foo)
return nil
}
@dgrijalva
Copy link
Author

go run renamer.go will read in the template source file and write an updated version to os.Stdout. Output looks like this:

package bar

import (
    "net/http"
)

type Bar struct {
}

func (b *Bar) Method(req *http.Request) *http.Response {
    _ = new(Bar)
    return nil
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment