2013-11-27 8 views
7

Mit Go ast package, ich Looping über ein Feld Liste der Struktur wie folgt:Holen Sie sich einen einfachen String-Darstellung eines Typs, der struct Feld

type Thing struct { 
    Field1 string 
    Field2 []int 
    Field3 map[byte]float64 
} 

// typ is a *ast.StructType representing the above 
for _, fld := range typ.Fields.List { 
    // get fld.Type as string 
} 

... und möchte eine einfache String-Darstellung von fld.Type bekommen, so wie es im Quellcode erscheint, zB "[] int" oder "map [byte] float64".

Das ast-Paket field type Typ-Eigenschaft ist ein Expr, also habe ich mich in die Unkräuter mit Typ-Schalter und Umgang mit jedem Typ speziell - wenn mein einziges Ziel ist es, die einfache Zeichenfolge rechts von jedem Feldname, der scheint, als sollte es einfacher sein.

Gibt es einen einfachen Weg?

+0

Haben Sie versucht 'theFileString [fld.Type.Pos(): fld.Type.End()]'? – mjibson

Antwort

11

Es gibt zwei Dinge, die Sie hier könnte man bekommen, ist einer der Typ eines Ausdrucks als würde letztlich während der Kompilierung aufgelöst werden und der andere ist der Code, die diese Art bestimmen würde.

Digging durch die Dokumente, ich glaube nicht, dass die erste überhaupt verfügbar ist. Sie können jedoch später unter Verwendung von End() und Pos() unter Node erreichen.

Schnellbeispielprogramm:

package main 

import (
    "fmt" 
    "go/ast" 
    "go/parser" 
    "go/token" 
) 

func main() { 
    src := ` 
     package foo 

    type Thing struct { 
    Field1 string 
    Field2 []int 
    Field3 map[byte]float64 
    }` 

    fset := token.NewFileSet() 
    f, err := parser.ParseFile(fset, "", src, 0) 

    if err != nil { 
     panic(err) 
    } 

    // hard coding looking these up 
    typeDecl := f.Decls[0].(*ast.GenDecl) 
    structDecl := typeDecl.Specs[0].(*ast.TypeSpec).Type.(*ast.StructType) 
    fields := structDecl.Fields.List 

    for _, field := range fields { 
     typeExpr := field.Type 

     start := typeExpr.Pos() - 1 
     end := typeExpr.End() - 1 

     // grab it in source 
     typeInSource := src[start:end] 

     fmt.Println(typeInSource) 
    } 

} 

Diese Drucke:

string 
[]int 
map[byte]float64 

ich durch diese zusammen in der golang playground, wenn Sie mit ihm zu verwirren wollen.

+0

Hilfreich und auch unglücklich. :) Das Datei-Geschäft ist in meinem Programm weit stromaufwärts, werde umstrukturieren müssen. –

0

fand ich einen Weg, dies zu tun, ohne den ursprünglichen Quellcode als Referenz für die einfachen Elemente (nicht Scheiben, Arrays oder Strukturen) mit:

  for _, field := range fields { 
       switch field.Type.(type) { 
       case *ast.Ident: 
        stype := field.Type.(*ast.Ident).Name // The type as a string 
        tag = "" 
        if field.Tag != nil { 
         tag = field.Tag.Value //the tag as a string 
        } 
        name := field.Names[0].Name //name as a string 
        ... 

Für die nicht einfache Mitglieder brauchen Sie nur einen anderen Fall Aussage (IE: case *ast.ArrayType:).