Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

text/template: {{call}} doesn't pass parameters to struct methods #10653

Closed
joncalhoun opened this issue May 1, 2015 · 2 comments
Closed

text/template: {{call}} doesn't pass parameters to struct methods #10653

joncalhoun opened this issue May 1, 2015 · 2 comments

Comments

@joncalhoun
Copy link

@joncalhoun joncalhoun commented May 1, 2015

Go version: go version go1.4.2 darwin/amd64
OS: OS X Yosemite Version 10.10.1

When using {{call ...}} in a template with a struct method the template parser fails to send any arguments to the method. This does work correctly if the method returns a function, or if the function you want to call is set to an attribute.

If this isn't intended to work, the error message could be a little clearer.

This can be replicated on the Go Playground here: https://play.golang.org/p/Ka8bN3_V1f and the source from the link is below.

package main

import (
    "os"
    "text/template"
)

type TestStructA struct {
    Test func(string) string
}

func test(s string) string {
    return "Test A Says " + s + "\n"
}

type TestStructB struct {
}

func (self TestStructB) Test() func(string) string {
    return func(s string) string { return "Test B Says " + s + "\n" }
}

// DOES NOT WORK
type TestStructC struct {
}

func (self TestStructC) Test(s string) string {
    return "Test C Says " + s + "\n"
}

func main() {
    tempStr := "{{call .Test \"hi\"}}"
    t := template.Must(template.New("test_temp").Parse(tempStr))

    testA := TestStructA{Test: test}
    err := t.Execute(os.Stdout, testA)
    if err != nil {
        panic(err)
    }

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

    // DOES NOT WORK
    testC := TestStructC{}
    err = t.Execute(os.Stdout, testC)
    if err != nil {
        panic(err)
    }
}
@robpike
Copy link
Contributor

@robpike robpike commented May 1, 2015

I admit the error message is poor but it is working as intended. You can't call something that doesn't have type func. If you look at case C, you'll see that it's missing one layer of "func" relative to cases A and B. Or, to put it another way, the evaluation of call's first argument must yield something of type 'func'. What it finds is a method, so it calls the method (without the tail of the action, which will become arguments to th function once it's evaluated). In cases A and B evaluating (calling) .Text yields another function, which call will invoke. But in case C, evaluating .Test fails because it a method of type func(string)string and there is no argument available. (Compare to {{call (.Test "hi") ''bye"}}.)

I believe you are just misunderstanding the call operation. The template you want for case C is just "{{.Test "hi"}}". The template you have is correct for cases A and B because the first argument to call evaluates (in the sense of calling the corresponding method) to a function whose type is func(string)string.

@robpike robpike closed this May 1, 2015
@mikioh mikioh changed the title text/template {{call}} doesn't pass parameters to struct methods text/template: {{call}} doesn't pass parameters to struct methods May 2, 2015
@joncalhoun
Copy link
Author

@joncalhoun joncalhoun commented May 7, 2015

Thanks for the info. Completely missed that part of the docs, and it makes complete sense after understanding how it works. 😄

@golang golang locked and limited conversation to collaborators Jun 25, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.