我有一组网络协议的XML描述,我试图从中生成Go代码,因此我没有任何现有的Go代码可以使用。所有使用go/ast
(例如go fmt
)的示例都会使用现有代码,对AST进行一些转换,然后将其写回。由于我所拥有的只是XML文件,因此我必须手工编写与我合作的AST。问题是我无法将手写的AST输出。
package main
import (
"go/ast"
"go/printer"
"go/token"
"os"
)
func main() {
f := ast.File{
Name: ast.NewIdent("foo"),
Decls: []ast.Decl{
&ast.GenDecl{
Tok: token.TYPE,
Specs: []ast.Spec{
&ast.TypeSpec{
Name: ast.NewIdent("Bar"),
Type: ast.NewIdent("uint32"),
},
},
},
},
}
fset := token.NewFileSet()
printer.Fprint(os.Stdout, fset, f)
}
预期产出:
package foo
type Bar uint32
实际输出:没有
如何打印AST?
答案 0 :(得分:4)
不要忽视错误!
添加:
err := printer.Fprint(os.Stdout, fset, f)
if err != nil {
log.Fatal(err)
}
给出:“ go / printer:不支持的节点类型ast.File ”,这应该足以让您指向正确的方向。
printer.Fprint
的最后一个参数是interface{}
,所以编译器接受任何东西。但是,就像parser.ParseFile
返回*ast.File
(而非ast.File
)一样,它需要一个指向节点的指针。
传递指针可以得到你想要的输出(注意&ast.File
):
package main
import (
"go/ast"
"go/printer"
"go/token"
"log"
"os"
)
func main() {
f := &ast.File{
Name: ast.NewIdent("foo"),
Decls: []ast.Decl{
&ast.GenDecl{
Tok: token.TYPE,
Specs: []ast.Spec{
&ast.TypeSpec{
Name: ast.NewIdent("Bar"),
Type: ast.NewIdent("uint32"),
},
},
},
},
}
fset := token.NewFileSet()
err := printer.Fprint(os.Stdout, fset, f)
if err != nil {
log.Fatal(err)
}
}