带开关和ForEach的Golang模板

Jen*_*ton 8 templates go

我需要从golang程序创建bash.sh文件,该文件应该执行以下操作:

创建的ForEach上依赖回路和读取的类型和根据打印类型不同的回波消息(命令)我需要它一起工作开关type与Golang的依赖性的

例如以下内容

对于每个依赖项,添加echo的类型消息

#!/bin/bash
for a in $(dependencies.type) 
  echo $runner  //from type 
done
Run Code Online (Sandbox Code Playgroud)

我做的是以下哪些不起作用

  1. 依赖关系类型"runner1"的想法(参见依赖结构实例中的type属性值)我需要运行几个命令,对于"runner2"我需要运行几个不同的命令
  2. 上面的那些命令(比如echo1的echo api1)应该写在我需要从模板创建的bash.script中

包主

import (
    "fmt"
    "log"
    "text/template"
    "gopkg.in/yaml.v2"
    "os"
)

type File struct {
    TypeVersion string `yaml:"_type-version"`
    Dependency  []Dependency
}

type Dependency struct {
    Name    string
    Type    string
    CWD     string
    Install []Install
}

type Install map[string]string

var data = `
_type-version: "1.0.0"
dependency:
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api

  - name: ui2
    type: runner2
    cwd: /ui2
    install:
       - name: api2

`

func main() {
    f := File{}

    err := yaml.Unmarshal([]byte(data), &f)
    if err != nil {
        log.Fatalf("error: %v", err)
    }

    d, err := yaml.Marshal(&f)
    if err != nil {
        log.Fatalf("error: %v", err)
    }
    fmt.Printf("--- t dump:\n%s\n\n", string(d))

    wd, _ := os.Getwd()

    newfile, err := os.Create(wd + "/" + "bash.sh") // Truncates if file already exists
    if err != nil {
        fmt.Errorf("Failed to create file: %s , %s", wd+"/"+"bash.sh", err)
    }

    fmt.Println(newfile)

    const File = `
#!/bin/bash
{{.dependency}},
{{if .Type runner2}}
 echo "type is runner2"
{{- else}}
echo "type is %S"
{{- end}}
{{end}}
`

    t := template.Must(template.New("bash.sh").Parse(File))

    for _, r := range f.Dependency {
        err := t.Execute(os.Stdout, r)
        if err != nil {
            log.Println("executing template:", err)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

更新

例如

假设我的映射如下,依赖结构应该与API结构一起使用,以了解为每个类型值运行的命令

API := map[string]string {
{
“runner1” : “api1”,
},
{
“runner2” : “api2”,
}
}
Run Code Online (Sandbox Code Playgroud)

这就是脚本最后应该是什么样子

#bin/bash

// in context of dep1
echo runner1
submitting api1


// in context of dep2
echo runner2
submitting api2
Run Code Online (Sandbox Code Playgroud)

Jon*_*ton 3

为实现上述目的进行一些最小的更改如下:

package main

import (
    "log"
    "text/template"
    "gopkg.in/yaml.v2"
    "os"
)

type File struct {
    TypeVersion string `yaml:"_type-version"`
    Dependency  []Dependency
}

type Dependency struct {
    Name    string
    Type    string
    CWD     string
    Install []Install
}

type Install map[string]string

var data = `
_type-version: "1.0.0"
dependency:
  - name: ui
    type: runner
    cwd: /ui
    install:
       - name: api

  - name: ui2
    type: runner2
    cwd: /ui2
    install:
       - name: api2

`

func main() {
    f := File{}

    err := yaml.Unmarshal([]byte(data), &f)
    if err != nil {
        log.Fatalf("error: %v", err)
    }

   const t = `
#!/bin/bash

{{range .Dependency}}
echo "type is {{.Type}}"
echo "cwd is {{.CWD}}"
{{range .Install}}
echo "install {{.name}}"
{{end}}
{{end}}
`

    tt := template.Must(template.New("").Parse(t))
    err = tt.Execute(os.Stdout, f)
    if err != nil {
        log.Println("executing template:", err)
    }
}
Run Code Online (Sandbox Code Playgroud)

这会产生

$ go run main.go 

#!/bin/bash


echo "type is runner"
echo "cwd is /ui"

echo "install api"


echo "type is runner2"
echo "cwd is /ui2"

echo "install api2"
Run Code Online (Sandbox Code Playgroud)

关键的更改是让模板完成工作 - 在 Dependency 数组上使用 range 函数,然后再次在 Install 数组上使用 range 函数来遍历数据结构。

另一个更改只是写入标准输出,而不是写入文件。如果需要将其转换为脚本,只需将其通过管道传输到文件即可。

更广泛地说,我认为围绕安装步骤的所有权的数据模型存在紧张关系。每种运行器类型的安装步骤是否固定?或者它们可能会有所不同?如果它们是固定的,那么将运行程序类型的映射[字符串] [字符串]安装到安装步骤数组可能是有意义的,这将减轻依赖对象拥有安装步骤副本的负担。

我还想知道 YAML——它是事实的来源吗?或者说它是衍生品?如果衍生的话,也许就没有必要了。让 go 程序询问实际的事实来源并生成脚本可能会更好。

无论如何,我希望这对您有所帮助。