2015-01-31 2 views
0

Мне нужно проанализировать файл исходного кода Go, найти определенный тип (по имени) и использовать его в моей программе. Мне уже удалось найти тот тип, который мне нужен, используя пакет go/ast, но я не знаю, как его загрузить в мою программу, чтобы я мог его использовать.Как оценивать внешний исходный код «динамически»?

Вопрос: Каков наилучший способ извлечь и использовать тип из внешнего файла исходного кода и использовать его во время выполнения?

Я не могу придумать ничего, кроме уродливого метода, чтобы в основном скопировать файл, изменить его, введя «основную» функцию с помощью материала кодирования, который отправляет результат на stdOut, выполняет его, собирает закодированные данные из stdout, удалите измененный файл.

использования: Анализ идти исходный код и кодировать типы в определенном формате (например, JSON-схему)

Edit: Вот код. Вопрос заключается в том, как закодировать type allTypes (нулевое значение), а затем распечатать его.

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" ??? 
} 

playground Также на

ответ

0

Если вам нужно извлечь информацию о типе во время выполнения, вы должны использовать reflect пакет. Так работает Go encoding/json и другие подобные пакеты.

+0

Я знаю об отраженном пакете, но вопрос совершенно другой. –

+0

@ Theuserwithnohat тогда, пожалуйста, отредактируйте свой вопрос и объясните, как он отличается, потому что пример, который вы дали (схема JSON), может быть выполнен с помощью 'reflect'. –

+0

Дело в том, что код загружается из внешнего файла/исходного кода. –

0

Если вы хотите работать с типами, определенными в исходном файле Go, вы можете использовать пакет go.parser для чтения и анализа исходного файла в AST, а затем пройти AST для элементов, которые вы хотите изучить.

+0

Проблема заключается в том, как использовать тип, найденный в исходном коде, и использовать его в текущей программе, которую я запускаю, не для того, чтобы анализировать исходный код. Я редактировал вопрос с помощью некоторого кода, чтобы убедиться, что проблема понятна. –

+0

Что вы хотите с этим делать? Из вашего вопроса совершенно не ясно, чего вы пытаетесь достичь в конечном итоге. В зависимости от ваших потребностей вы можете просто проверить поля в типе, загруженном из источника, и самостоятельно вывести необходимый JSON. –

+0

В примере, представленном в вопросе, я закодировал '' sometype'', который является частью запущенной программы.Вопрос заключается в том, как просто кодировать '' alltype'', который не является частью основной программы (я загрузил источник как строку, поскольку игровая площадка не имеет доступа к файлу). –

0

Кажется, что нет способа загрузить информацию о типе, извлеченную из исходного кода (пожалуйста, поправьте меня, если я ошибаюсь). Единственное решение - создать/сгенерировать пакет (основной), вставить его всеми типами, извлеченными из целевого файла исходного кода, собрать/скомпилировать его, выполнить и собрать закодированные данные из stdout.

1

Если я понимаю, вы просите загрузить динамический тип ala Java Class.forName(String className). Короткий ответ: Go не поддерживает это.

Правильный способ, как указал Ник Джонсон, - проанализировать дерево, используя ast, а затем «сгенерировать» JSON самостоятельно. Вы не сможете «загрузить» тип и использовать JSON.Marshal. Также стоит отметить, что любой тип, поддерживающий интерфейс json.Marshaler, может генерировать пользовательский JSON. Вам также необходимо игнорировать, но отметить необязательное поведение «omitempty». Это действительно мешает вам использовать компиляцию и взломать поведение «stdout».

+0

Не могли бы вы поделиться фрагментом, который кодирует '' allType'', как указано в вопросе? Вопрос в том, каков наилучший способ использования решения этой проблемы, поэтому я предполагаю, что анализ синтаксиса и кодирование должны быть проще, чем компиляция и stdout, правильно? –

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