Using Methods with Multiple Return Values

I am trying to write a template (using html / template) and pass it a structure to which some methods are bound, many of which return multiple values. Is there any way to access them from the template? I would like to be able to do something like:

package main import ( "fmt" "os" "text/template" ) type Foo struct { Name string } func (f Foo) Baz() (int, int) { return 1, 5 } const tmpl = `Name: {{.Name}}, Ints: {{$a, $b := .Baz}}{{$a}}, {{b}}` func main() { f := Foo{"Foo"} t, err := template.New("test").Parse(tmpl) if err != nil { fmt.Println(err) } t.Execute(os.Stdout, f) } 

But obviously this will not work. Is there no way around this?

I considered creating an anonymous structure in my code:

 data := struct { Foo a int b int }{ f, 0, 0, } data.a, data.b = f.Baz() 

And passing it on, but would rather have something in the template. Any ideas? I also tried to write a wrapper function that I added to funcMaps, but I could never get it to work.

Thanks for any suggestions!

+5
source share
3 answers

You cannot call a function that returns two values ​​in a template if one of these values ​​is not an error. This ensures that your template will work at runtime. There is a great answer explaining what is here if you are interested.

To solve your problem, you need to either: 1) split your function into two separate getter functions, which you can call in the appropriate place of your template; or 2), your function returns a simple structure with values ​​inside.

I can’t say what will be better for you, because I really don’t know what your implementation requires. Foo and Baz don't give a lot of clues .;)

Here is an example with a quick n-dirty option:

 type Foo struct { Name string } func (f Foo) GetA() (int) { return 1 } func (f Foo) GetB() (int) { return 5 } 

And then modify the template accordingly:

 const tmpl = `Name: {{.Name}}, Ints: {{.GetA}}, {{.GetB}}` 

Hope this helps. :)

+4
source

It is also possible to return a struct with multiple fields and use them.

 type Result struct { First string Second string } func GetResult() Result { return Result{First: "first", Second: "second"} } 

And then use in the template

 {{$result := GetResult}} {{$result.First}} - {{$result.Second}} 
+1
source

I recently had a problem similar to this, and I came across this question. I think it might be a little cleaner. It is not required to create several new functions:

 const tmpl = 'Name: {{.Name}}, Ints: {{BazWrapper .}}' func main() { f := Foo{"Foo"} funcMap := template.FuncMap{ "BazWrapper": func(f Foo) string { a, b := f.Baz() return fmt.Sprintf("%d, %d", a, b) }, } t, err := template.New("test").Funcs(funcMap).Parse(tmpl) if err != nil { fmt.Println(err) } t.Execute(os.Stdout, f) } 
0
source

All Articles