gotemplatesgo-templates

Golang html/template "wrong number of args want 1 got 0" using 'call' in template


I'm developing a Go! application using the html templating built-in library. In my template, the following works:

  {{range .industries }}
  ...
    <td style="text-align:right">{{ .SalesStock.Size }}</td>
  ...
  {{ end }}

industries is a slice of objects of type Industry. SalesStock is a method of Industry and yields an object SalesStock of type Stock, which has a field Size.

This code works fine.

In place of Size I want to call a method that will display either the Size or the Price field, depending on a parameter mode.

The (simplified) method is

func (stock Stock) DisplaySize(mode string) float32 {
    switch mode {
    case `price`:
        return stock.Size
    case `size`:
        return stock.Price
    default:
        panic("unknown display mode requested")
    }
}

I replaced the line in the template with:

   <td style="text-align:right">{{ call .SalesStock.DisplaySize "size" }}</td>

and received the error

  at <.SalesStock.DisplaySize>: wrong number of args for DisplaySize: want 1 got 0

What did I do wrong?

thanks for any offers. I suspect the mistake is elementary. I'm new to Go.


Solution

  • The builtin call is to call a function value. You want to call a method, simply remove call and it'll work:

    {{ .SalesStock.DisplaySize "size" }}
    

    You would need call if DisplaySize would be a regular field (of function type) and you'd want to call that.

    For example:

    type Stock struct {
        Size      float32
        Price     float32
        FuncField func(param string) string
    }
    
    func (stock Stock) DisplaySize(mode string) float32 {
        switch mode {
        case `price`:
            return stock.Price
        case `size`:
            return stock.Size
        default:
            panic("unknown display mode requested")
        }
    }
    
    func main() {
        const src = `{{.SalesStock.DisplaySize "size"}}
    {{.SalesStock.DisplaySize "price"}}
    {{ call .SalesStock.FuncField "Foo"}}`
    
        t := template.Must(template.New("").Parse(src))
    
        p := map[string]any{
            "SalesStock": Stock{
                Size:      2,
                Price:     3,
                FuncField: func(param string) string { return param + param },
            },
        }
    
        err := t.Execute(os.Stdout, p)
        if err != nil {
            panic(err)
        }
    }
    

    This will output (try it on the Go Playground):

    2
    3
    FooFoo