-1

Im using Golang project which needs to generate the following

app1 && app2 && app3

My template look like following

{{- range ExeApp .}} {{ .Command }} {{- end}}

My code looks like following with command which is array of strings

type App struct {
   Data    string
   Command []string
}

//This is the function
func ExeApp(m models) []App {

   switch m.Type {
   case “apps":
      return []App{
         {"# running apps",
            []string{“app1", “app2", “app3"}},
      }

…

Currently its generated like

[app1 app2 app3]

And I need it like

app1 && app2 && app3 ,

I try to play with the template by adding && before the .Command which doesn’t help and in addition I don’t know how to remove the array [] before and after the apps, any idea what I’m doing wrong here ?

i've tried with the following

{{- range .ExeApp}} {{range .Command }} && {{.}} {{end}} {{- end}}

But now im getting dump with error: unexpected EOF or function "Command" not defined

while running the template

The code to generate is:

funcMap := template.FuncMap{
    "ExeApp": ExeApp,
}
t, err := template.New("file.txt").Funcs(funcMap).ParseFiles(container)

in case Im working with the first structure (same structure without the array of strings and of course adapt the code of the object) everything is working as expected

Try also with this {{-range .ExeApp}} {{range .Command}} {{.}} {{end}} {{end}}

Now im getting error

executing "file.txt" at <.ExeApp>: can't evaluate field ExeApp in type *models

why :(

07_05_GuyT
  • 2,787
  • 14
  • 43
  • 88

1 Answers1

1

In your final example you have two ranges and only one end (prior to your edit!)

Now that is fixed, are you sure you don't have a space between the dot and Command? Try putting an example on play.golang.org as the errors don't match what you have shown - funcs from funcmap don't have a dot prefix.

Then to avoid trailing && you'll need to use the variant of range with an index, put the && before and only print if index > 0

I think you want something like this:

https://play.golang.org/p/O8rpum8LtZr

// Define a template.
const tmpl = `
{{ range . -}}
{{range $i,$a := .Command}}{{if gt $i 0 }} && {{end}}{{.}}{{end}}
{{end}}
`

// Prepare some data
type App struct {
    Data    string
    Command []string
}
data := []App{App{"test data", []string{"app1", "app2", "app3"}}}

// Create a new template and parse into it.
t := template.Must(template.New("tmpl").Parse(tmpl))

// Execute the template with data
err := t.Execute(os.Stdout, data)
if err != nil {
    log.Println("executing template:", err)
}

Read the docs for text/template before proceeding, to clear up a few misunderstandings - funcs don't take ., you may not need a func at all, don't use them to pass data in use a context for that (data in my example).

Also perhaps consider in this example whether you want to use text/template at all - if the strings you are building are command line arguments you may well want to look at examples for the os/exec package instead.

Use {{ range ExeApp }} (note no dot) if you want to use the data returned from a function. Your example introduces several errors! If you must use a funcmap for data, here is how you'd do it:

https://play.golang.org/p/euWxctWRbp_L

Please do read the docs though, funcs don't use the dot prefix (that's rather important), and also funcmaps are for helpers, not data, you are storing up problems for yourself if you rely on funcmaps for data, as you will make it harder to tell where the data comes from, harder to debug the handlers etc.

Kenny Grant
  • 9,360
  • 2
  • 33
  • 47
  • Can you please update your answer with the exact code ? – 07_05_GuyT Jul 29 '18 at 17:38
  • im using `{{- range .ExeApp}} {{range .Command }} && {{.}} {{end}} {{- end}}` and getting error, what am I missing here ? – 07_05_GuyT Jul 29 '18 at 17:39
  • even if I remove the `&&` im getting error `function Command" not defined ` – 07_05_GuyT Jul 29 '18 at 17:42
  • This is the last version `{{-range .ExeApp}} {{range .Command}} {{.}} {{end}} {{-end}}` – 07_05_GuyT Jul 29 '18 at 17:49
  • so it should be like what I put in my last comment ? or something else – 07_05_GuyT Jul 29 '18 at 17:51
  • Thanks 1+, but my code use FuncMap, how should I do it in this case ? – 07_05_GuyT Jul 29 '18 at 19:14
  • The function which is returning this data is `ExeApp`, I must use it... – 07_05_GuyT Jul 29 '18 at 19:25
  • if I can use function that returning `data := []App{App{"test data", []string{"app1", "app2", "app3"}}}` it will be great (with FuncMap), this will solve the issue – 07_05_GuyT Jul 29 '18 at 19:26
  • Thanks, well this is part from a bigger template which is divided to functions..., the dot is not helping becouse the template miss the cotext, where does the ExeApp function should be take part, I dont see anything in the template which is related to the function which return the `data`... – 07_05_GuyT Jul 30 '18 at 05:04
  • added a new last line. if you read the docs this should become clear. – Kenny Grant Jul 30 '18 at 06:43
  • I've read the docs and here its a bit more complicated, where should I put the {{ range ExeApp }} , can you please update the sample you have created with the funcMap , this is what I miss here? – 07_05_GuyT Jul 30 '18 at 06:47
  • I think that this example is closer to what I need but I couldn't make it work :( https://play.golang.org/p/C3U2vw_cDo_k – 07_05_GuyT Jul 30 '18 at 06:59
  • Thanks, im checking it now – 07_05_GuyT Jul 30 '18 at 07:53
  • Looks good, thanks a lot.that my function `ExeApp(m model)` is having parameter (in real life) , how it should be adopted {{ range ExeCmd - }} in this case ? – 07_05_GuyT Jul 30 '18 at 08:01
  • You said in your comments that I need to use function just for helpres but lets assume that I've big template which needs to generate different thiings from diffrent data how would you hande lit ? – 07_05_GuyT Jul 30 '18 at 08:14
  • Context can be a struct containing all the data you need or a map[string]interface{} to contain arbitrary data. – Kenny Grant Jul 30 '18 at 08:15
  • but it's different type of data and different structures of data why I need to combine them ? – 07_05_GuyT Jul 30 '18 at 08:16
  • in funcMap for my opinion you can spreate the data sources value, each func sends different data, is it wrong ? – 07_05_GuyT Jul 30 '18 at 08:17
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177000/discussion-between-shopia-t-and-kenny-grant). – 07_05_GuyT Jul 30 '18 at 08:26
  • Thanks for your help :) – 07_05_GuyT Jul 30 '18 at 08:35