0

I need to parse a Go source code file, find a specific type (by name) and use it in my program. I already managed to find the type I need using the go/ast package but I don't know how to "load" it into my program so that I can use it.

Question: What's the best way to extract and use a type from an external source code file and use it on runtime?

I can't think of anything except an ugly method to basically copy the file, modify it by injecting a "main" function with my encoding stuff which sends the result to stdOut, execute the it, collect the encoded data from stdout, delete the modified file.

Use case: Analyse go source code and encode the types in a specific format (e.g. json schema)

Edit: Here is some code. The question is how to encode type allTypes (zero value) and then print it.

package main

import (
    "fmt"
    "go/ast"
    "go/parser"
    "go/token"
    "encoding/json"
)
    var src string = `
package mypack

type allTypes struct{
    Brands Brands
    Colours Colours
}
type Brands struct{
    Sony string
    Apple string
}

type Colours struct{
    Red string
    Green string
}

`
type sometype struct{
    Nothing int
}
func main() {
    // src is the input for which we want to inspect the AST.

    // Create the AST by parsing src.
    fset := token.NewFileSet() // positions are relative to fset
    f, err := parser.ParseFile(fset, "src.go", src, 0)
    if err != nil {
        panic(err)
    }

    // Inspect the AST and find our function
    var tp ast.TypeSpec
    ast.Inspect(f, func(n ast.Node) bool {
        switch x := n.(type) {
        case *ast.TypeSpec:
            if x.Name.Name == "allTypes"{
                tp = *x
            }
        }
        return true
    })

    fmt.Printf("We found the type: it is %v", tp)
    // Encode the zero value of sometype
    x := sometype{}
    b, _ := json.Marshal(&x)
    fmt.Printf("\n Zero value of someType (json) %s", b)
    //Next/Question: How to encode the zero value of "allTypes" ???
}

Also on playground

4 Answers 4

1

If I understand you are asking for dynamic type loading ala Java's Class.forName(String className). The short answer is Go doesn't support this.

The correct way, as Nick Johnson pointed out, is to parse the tree using ast, and then "generate" the JSON yourself. You will not be able to "load" the type and use JSON.Marshal. It is also worth noting that any type which supports the json.Marshaler interface may generate custom JSON. You also need to ignore, but mark optional "omitempty" behavior. This really prevents you from using the compile it and hack through "stdout" behavior as well.

Sign up to request clarification or add additional context in comments.

1 Comment

would you mind to share a snippet which encodes allType as provided in the question? The question is actually what's the best way to use solve this problem so I assume that the ast parsing & encoding should be easier than compile & stdout, right?
0

If you need to extract type information at runtime, you need to use the reflect package. This is the way Go's encoding/json and other similar packages work.

3 Comments

I'm aware of the reflect package but the question is quite different.
@Theuserwithnohat then please edit your question and explain how it is different, because the example you've given (JSON schema) can be done with reflect.
The point is that the code is loaded from an external file / source code.
0

If you want to operate on the types defined in a Go source file, you can use the go.parser package to read and parse a source file into an AST, then traverse the AST for the elements you want to examine.

9 Comments

The issue is how to use the type found in the source code and use it in the current program I'm running not how to parse the source code. I've edited the question with some code to make sure the issue is understood.
What do you want to do with it? It's not at all clear from your question what you're trying to ultimately achieve. Depending on your needs, you may simply have to inspect the fields in the type loaded from the source and output the necessary JSON yourself.
In the example provided in the question I've encoded sometype which is part of the running program. The question is simply how to encode alltype too which is not part of the main program(I've loaded the source as a string as the playground doesn't have file access).
Can you please point me how to do this that? (inspect the fields in the type loaded from the source and output the necessary JSON). The main issue is that I can't find a way to "load" the type from source code. As far what I'm trying to do let's say that I want to extract some types from a *.go source code file and encode them so that they can serve as "documentation". In the question I've used the json package but I'm actually planning to use json schema which basically "documents" the types for web applications. You may think of this as godoc for web.
You should expect the TypeSpec to contain a StructType in its node field; you can then iterate over its FieldList to get all the fields and their data types, and output those however you wish.
|
0

It seems there is no way to load the type information extracted from the source code(please correct me if I'm wrong). The only solution is to create/generate a package (main), inject it with all the types extracted from the target source code file, build/compile it, execute it and collect the encoded data from stdout.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.