Golang-文本/模板返回键值

I need to return form the text template key value which will be like comment and command like following

 #Description for npm install 
   npm install
 #Description for test
   npm test
 #Description for test2 
   run test2

For that I've created a function like the following:

// example with switch
func (d Dependency) TypeCommand() Command {
    switch d.Type {
    case "runner":

        cmd1 := Command{"#Description for npm install", "npm install"}
        cmd2 := Command{"#Description for test", "npm test"}
        cmd3 := Command{"#Description for test2", "run test2"}

    case "runner2":
        return "test 2"

    }
    return "command_baz"
}

The template is:

const tmpl = `
{{- range .File.Dependency}}

{{.TypeCommand}}
{{end}}`

type Command struct {
    Info    string
    Command string
}

When I change the template to the following, I get an error:

const tmpl = `
    {{- range .File.Dependency}}

     {{  TypeCommand .}}
   {{ range .Command}}
    {{ .Info }}
    {{ .Command }}
   {{end}}
  {{end}}
        '

executing "tmpl3.txt" at <.Command>: can't evaluate field Command in type *Dependency

I use this as reference.

The error message you're getting is because you're just throwing away the return value of TypeCommand instead of passing it on to where you try to access its struct fields. We could fix that, but that's probably not what you wanted to do anyways, since your TypeCommand function looks like it should probably be returning multiple commands instead of a single one. So let's re-write that first:

func (d Dependency) TypeCommand() []Command {
    switch d.Type {
    case "runner":

        return []Command{
          Command{"#Description for npm install", "npm install"},
          Command{"#Description for test", "npm test"},
          Command{"#Description for test2", "run test2"},
        }

    case "runner2":
        return []Command{Command{"#test 2", "foo"}}

    }
    return []Command{Command{"#command_baz", "baz"}}
}

Now that we're returning multiple commands, we can just range over them in the template and they'll be automatically bound. I tweaked your template a little bit to the following:

const tmpl = `
{{- range .File.Dependency}}
  {{- range .TypeCommand }}
{{ .Info}}
  {{ .Command}}
{{- end}}{{end}}`

When I ran this in the Go Playground, this got me the following output, which seemed to be what you were going for:

#Description for npm install
  npm install
#Description for test
  npm test
#Description for test2
  run test2
#test 2
  foo
    package main

import (
    "os"
    "text/template"
)

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

type Dependency struct {
    Name string
    Type string
    CWD  string
}

type Command struct {
    Info    string
    Command string
}

func  (d Dependency) TypeCommand() []Command {
    switch d.Type {
    case "runner":

        return []Command{
          {"#Description for npm install", "npm install"},
          {"#Description for test", "npm test"},
          {"#Description for test2", "run test2"},
        }

    case "runner2":
        return []Command{{"#test 2", "foo"}}

    }
    return []Command{{"#command_baz", "baz"}}
}

type Install map[string]string

const tmpl = `
{{- range .File.Dependency}}
  {{- range .TypeCommand }}
{{ .Info}}
  {{ .Command}}
{{- end}}{{end}}`

type API map[string]string

func main() {
    f := new(File)
    f.Dependency = []Dependency{{
        Name: "ui",
        Type: "runner",
        CWD:  "/ui",
    }, {
        Name: "ui2",
        Type: "runner2",
        CWD:  "/ui2",
    }}

    t, err := template.New("t").Parse(tmpl)
    if err != nil {
        panic(err)
    }

    var data struct {
        File *File
        API  API
    }
    data.File = f

    if err := t.Execute(os.Stdout, data); err != nil {
        panic(err)
    }
}

This Should Work Properly.

The main problem was with the return type of the method of Dependency