为了账号安全,请及时绑定邮箱和手机立即绑定

如何“动态”评估外部 go 源代码?

如何“动态”评估外部 go 源代码?

Go
繁花不似锦 2021-09-13 14:56:57
我需要解析 Go 源代码文件,找到特定类型(按名称)并在我的程序中使用它。我已经设法使用go/ast包找到了我需要的类型,但我不知道如何将它“加载”到我的程序中以便我可以使用它。问题:从外部源代码文件中提取和使用类型并在运行时使用它的最佳方法是什么?除了一个丑陋的方法来基本上复制文件,通过注入一个“main”函数来修改它,我的编码内容将结果发送到stdOut,执行它,从stdout收集编码数据,删除修改后的文件。用例:分析 go 源代码并以特定格式(例如 json 模式)对类型进行编码编辑:这是一些代码。问题是如何编码type allTypes(零值)然后打印出来。package mainimport (    "fmt"    "go/ast"    "go/parser"    "go/token"    "encoding/json")    var src string = `package mypacktype 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" ???}也在操场上
查看完整描述

3 回答

?
拉丁的传说

TA贡献1789条经验 获得超8个赞

如果我了解您要求动态类型加载 ala Java 的Class.forName(String className). 简短的回答是 Go 不支持这一点。

正如 Nick Johnson 指出的那样,正确的方法是使用 ast 解析树,然后自己“生成”JSON。您将无法“加载”类型并使用JSON.Marshal. 还值得注意的是,任何支持该json.Marshaler接口的类型都可能生成自定义 JSON。您还需要忽略,但标记可选的“省略”行为。这确实可以防止您使用编译它并通过“stdout”行为进行破解。


查看完整回答
反对 回复 2021-09-13
?
蝴蝶不菲

TA贡献1810条经验 获得超4个赞

如果需要在运行时提取类型信息,则需要使用该reflect包。这是 Goencoding/json和其他类似包的工作方式。


查看完整回答
反对 回复 2021-09-13
  • 3 回答
  • 0 关注
  • 183 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信