14

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.

7
  • If you require the --type option for every invocation, you might consider using subcommands instead: extract format --format=json or extract order --format=xml Commented Mar 22, 2018 at 13:14
  • yes that's what i mean Commented Mar 22, 2018 at 15:09
  • In TypeCommand why are you returning String and mentioning return type as Dependency ? Commented May 27, 2018 at 10:36
  • @TarunLalwani - No , this is mistake, I need to return the key value to print it from the template latter, any idea how it can be done? Commented May 27, 2018 at 10:43
  • It would be helpful if your Command struct and Command struct field were named different things. Commented May 27, 2018 at 12:53

2 Answers 2

4
+25

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
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks, im trying it now and let you know
I try it now and I got the same error, did you able to make the playground work?
please see: play.golang.org/p/o16HBPv7agr , I must use the function of TypeCommand as is, any idea how to overcome it like this?
the func structure should be like func TypeCommand(d Dependency) []Command { and not like func (d Dependency) TypeCommand() []Command { , how can I make it work like this?
If you insist on using the func structure you've provided in your updated example, you'll need to use a FuncMap, per this playground example: play.golang.org/p/L5lqvWTyzlV
|
-1
    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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.