2015-02-24 4 views
0

У меня есть набор XML-описания сетевого протокола, который я пытаюсь сгенерировать код Go, поэтому у меня нет никакого существующего кода Go для работы. Все примеры, которые используют go/ast (например, go fmt), имеют существующий код, делают некоторые преобразования в AST, а затем записывают их обратно. Поскольку у меня есть файлы XML, AST, с которыми я работаю, должен быть написан вручную. Проблема в том, что я не могу получить свой письменный АСТ для вывода.Как печатать рукописные АСТ?

Example

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 для печати?

ответ

4

Не игнорируйте ошибки!

Добавление:

err := printer.Fprint(os.Stdout, fset, f) 
if err != nil { 
    log.Fatal(err) 
} 

дает: «идти/принтер: неподдерживаемый узел типа 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) 
    } 
} 

playground

+1

+1 для одной только первой линии. Отлично, что он также отвечает на этот вопрос, но игнорировать ошибки - это плохая привычка. – sberry

+1

К сожалению. Дело не в том, что я знал, что «printer.Fprint» возвращает ошибку, и я целенаправленно игнорировал его, но я использовал его, как будто это 'fmt.Printf', где обычно проверка ошибок не выполняется. Тупой вопрос, но спасибо за ответ, хотя! Разрывал мои волосы, почему что-то так же просто, как печать не работает ... – user1698814

Смежные вопросы