我有一个具有以下内容的YAML文件:
name: foo
port: 8080
routes:
route: /echo
method: GET
body: Hello back!!!!
route: /greet
method: GET
body: Hello, how are you!!!
从YAML文件中,我想生成具有以下内容的GO应用程序:
package main
import (
"net/http"
"github.com/labstack/echo"
)
func main() {
e := echo.New()
e.GET("/echo", func(c echo.Context) error {
return c.String(http.StatusOK, "body: Hello back!!!!")
})
e.GET("/greet", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, how are you!!!")
})
e.Logger.Fatal(e.Start(":8080"))
}
最后,它应该编译一个随时可用的GO应用程序。我可以使用https://golang.org/pkg/text/template/来构建GO应用程序,还是有其他解决方案?
创建文件main.go
package main
import (
"gopkg.in/yaml.v2"
"io/ioutil"
"log"
"os"
"text/template"
)
type Routes struct {
Route string `yaml:"route"`
Method string `yaml:"method"`
Body string `yaml:"body"`
}
type Service struct {
Name string `yaml:"name"`
Port string `yaml:"port"`
Routes []Routes
}
var serviceTpl = `
package main
import (
"net/http"
"github.com/labstack/echo"
)
func main() {
e := echo.New()
{{range .Routes}}
e.{{.Method}}("{{.Route}}", func(c echo.Context) error {
return c.String(http.StatusOK, "{{.Body}}")
})
{{end}}
e.Logger.Fatal(e.Start(":{{.Port}}"))
}
`
func loadConfig(yamlPath string) (c Service) {
if yamlPath == "" {
log.Fatalf("missing YAML configuration")
}
f, err := ioutil.ReadFile(yamlPath)
if err != nil {
log.Fatalf("failed to read YAML file: %v", err)
}
if err := yaml.Unmarshal(f, &c); err != nil {
log.Fatalf("failed to decode configuration: %v", err)
}
return
}
func generateService(c Service, outputPath string) {
t, err := template.New("Service").Parse(serviceTpl)
if err != nil {
log.Fatalf("failed to parse template: %v", err)
}
f, err := os.Create(outputPath)
if err != nil {
log.Fatalf("failed to create file '%s': %v", outputPath, err)
}
if err := t.Execute(f, c); err != nil {
log.Fatalf("failed to generate service: ", err)
}
}
func main() {
c := loadConfig(os.Args[1])
generateService(c, os.Args[2])
}
生成文件,并使用可执行文件
go build -o executable-name
./executable-name my_input.yml my_output_file.go
基本上,有两种解决此类问题的方法:
“普通”文本转换。
您接受输入文本,然后进行[[翻译以遵循一组简单规则输出文本。
是的,您可以为此使用任何合适的模板引擎。基本上,您将输入的YAML解析为一组(struct
类型的Go值),然后对该集合运行模板以生成输出文本。此方法不“了解” Go的任何内容。
这是第一种方法的一种变体,它不是盲目地操纵文本,而是实际上以抽象形式生成一个Go程序,然后将其[[formats转换为准确描述它的源代码文件。
将输入的YAML解析为一组(struct
类型的)Go值-与上面一样。
纯文本转换通常在生成格式正确的Go源代码时会遇到麻烦(因此,在其上运行gofmt -s -l
会产生空输出)。
通过AST生成代码在实现方面是一项更为复杂的任务-因为它需要您考虑“低级”内容,例如构成程序抽象形式的单个令牌,但总的来说,您要获得两点上面的代码是“免费”分类的-因为stdlib提供的Go源代码格式化程序无需任何额外的努力即可以规范的形式生成源代码,并且还处理了用字符串文字正确地掩盖怪异事物的所有麻烦。