What is the difference between running a function in a .go file and invoking it in Go template?

huangapple go评论82阅读模式
英文:

What is the difference between running a function in a .go file and invoking it in Go template?

问题

通过text/template包中的template.FuncMap,您可以直接在Go模板文件中访问函数。

假设以下情景:在用户概览页面的处理程序中,您调用一个名为GetAllUsers的函数,并使用ExecuteTemplate将用户对象传递给模板:

func index(w http.ResponseWriter, r *http.Request) {
  users, err := model.GetAllUsers()
  if err != nil {
    render50x()
    return
  }

  data := make(map[string]interface{})
  data["userList"] = users

  render(w, r, data, "layout", "index")
}

这与将函数传递给模板并在模板中执行它有什么区别吗?

var funcs = template.FuncMap{
  "getAllUsers": model.GetAllUsers,
}

// func render
t := template.New("render").Funcs(funcs)
if err := template.Must(t.ParseFS(ViewsFS, files...)).ExecuteTemplate(w, layout, data); err != nil {
  log.Println("Error executing template:", err.Error())
}

{{ range getAllUsers }}
  {{ .DisplayName }}
{{ end }}

这两种方法之间有什么区别吗?

英文:

With template.FuncMap from the text/template package, you can directly access functions from within your Go template files.

Suppose the following scenario: In your handler for a user overview page, you call a function GetAllUsers and pass your user objects to the template with ExecuteTemplate:

func index(w http.ResponseWriter, r *http.Request) {
  users, err := model.GetAllUsers()
  if err != nil {
    render50x()
    return
  }

  data := make(map[string]interface{})
  data["userList"] = users

  render(w, r, data, "layout", "index")
}

Is this the same as passing the function to the template and executing it there?

var funcs = template.FuncMap{
  "getAllUsers": model.GetAllUsers,
}

// func render
t := template.New("render").Funcs(funcs)
if err := template.Must(t.ParseFS(ViewsFS, files...)).ExecuteTemplate(w, layout, data); err != nil {
  log.Println("Error executing template:", err.Error())
}

{{ range getAllUsers }}
  {{ .DisplayName }}
{{ end }}

Is there a difference between the two approaches?

答案1

得分: 2

如果你可以从模板中调用函数,那么它是相同的。但是有一些区别:

如果你在Go中调用函数,你不需要注册该函数。有时候你无法访问模板解析来注册函数,所以这是唯一的方法(不要忘记:你必须在解析模板之前注册函数)。

此外,如果你在Go中调用函数,你对它有更多的"控制":你可以从panic中恢复,可以预处理结果,并且可以在其他Go代码中重复使用它。你还可以选择根据结果来决定是否执行模板,或者执行一些在模板中(很难)表达的其他操作。

函数的结果可能不是容易渲染的东西。例如,它可能不是一个string,或者可能没有一个String() string方法。因此,可能需要一些额外的(Go)逻辑来将结果转换为人类可读的格式,这在模板中可能不可用,或者可能需要进一步注册其他函数。

还要注意,并非所有的函数都可以在模板中注册和调用。可调用的函数最多可以有2个返回类型,第二个返回类型只能是error。从Go中,你可以调用"任何"函数并只传递你需要的结果。如果函数有参数,你还必须将这些参数作为数据传递给模板执行(所以在调用函数时,你可以在模板中传递它们)。

英文:

If you can call the function from the template, it's the same. Some differences:

If you call it in Go, you do not need to register the function. Sometimes you don't have access to template parsing to register functions, so this is the only way (don't forget: you have to register functions before parsing the template).

Also if you call it in Go, you have more "control" over it: you can recover from panics, you can pre-process the results, and you can re-use it in other Go code. You can also choose not to execute the template based on the result, or do something else which may not be (easily) expressible in templates.

The result of the function may also not be something that can be rendered easily. E.g. it may not be a string, or may not have a String() string method. So some additional (Go) logic may be needed to convert the result to a human-readable format, which may not be available in templates, or may require further functions to be registered.

Also note that not all functions can be registered and called from templates. Callable functions may have 2 return types at most, the seconds which may only be error. From Go you can call "any" functions and pass only the results you need. If the function has parameters, you also have to pass those as data to the template execution (so you can pass them in the template when calling the function).

huangapple
  • 本文由 发表于 2023年2月3日 19:33:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75335128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定