douman9420 2017-10-01 10:06
浏览 140

带开关和ForEach的Golang模板

I need to create bash.sh file from golang program which should do the following:

Create ForEach loop on dependencies and read the type and according to type print different echo message (commands) I need it to work with switch on the type of the dependency with Golang

e.g. something like following

For each dependency entry add the type message of echo

#!/bin/bash
for a in $(dependencies.type) 
  echo $runner  //from type 
done

what I did is the following which doesn't work

  1. The idea that for dependencies type "runner1"(see the type property value in dependency struct instance) I need to run several commands and for "runner2" I need to run several different commands
  2. And those commands (like echo api1 for runner1 etc )above should be written in the bash.script that I need to create from the template

package main

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:
%s

", 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)
        }
    }

}

update

For example

lets say i’ve map like following and the dependencies struct should work with the API struct to know which command to run for each type value

API := map[string]string {
{
“runner1” : “api1”,
},
{
“runner2” : “api2”,
}
}

This is how should the script look like at the end

#bin/bash

// in context of dep1
echo runner1
submitting api1


// in context of dep2
echo runner2
submitting api2
  • 写回答

1条回答 默认 最新

  • dpjhq00684 2018-04-18 15:46
    关注

    Some minimal changes to get to working for the above are here:

    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)
        }
    }
    

    This produces

    $ 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"
    

    The key change is to let the template do the work- use the range function on the Dependency array, and then again on the Install array, to traverse the data structure.

    The other change is just to write to stdout, rather than to a file. If it is desirable to turn this into a script, just pipe it to a file.

    More broadly, I think there is a tension in the data model around ownership of the install steps. Are the install steps fixed for each runner type? Or may they vary? If they are fixed, then having a map[string][string] of runner type to array of install steps probably makes sense, which would then relieve the Dependency object of having a copy of install steps.

    I also wonder about the YAML- is it a source of truth? Or is it derivative? If derivative, perhaps it is unnecessary. Probably better to have the go program interrogate the actual source of truth and generate a script.

    In any event, I hope that's helpful.

    评论

报告相同问题?

悬赏问题

  • ¥15 基于单片机数字电压表电路组成及框图
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line