使用Golang向HTML模板传递值的方法
首先
在Go语言中,您可以使用http/template将值传递到HTML模板中。
就这一点来说
-
- 変数
-
- スライス
-
- マップ
- 構造体
这些都是值之一。
在本次讲解中,我们将会解释基本变量和最常见的结构体的使用情况。
因为在搜索的过程中并没有找到太多相关的信息,所以我写下了一些关于用于网页开发的技术。
环境
-
- macOS Catalina 10.15
go 1.12.9
0. 不传递任何东西而执行。
这是主要的Go和html文件。
我会以这些为基础进行解释。
.
├── main.go
└── tpls.html
package main
import (
"html/template"
"log"
"os"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseFiles("tpls.html"))
}
func main() {
err := tpl.Execute(os.Stdout, nil) // dataは渡さない
if err != nil {
log.Fatalln(err)
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>hoge</h1>
</body>
</html>
以下是使用go run main.go命令执行main.go后的结果。
$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>hoge</h1>
</body>
</html>⏎
真的没有什么特别之处呢。
由于此次在终端进行了标准输出,所以会完整显示全部文本,但实际上应该通过web浏览器加载,只会显示”hoge”。
让我们来看一下模板的使用方法。
将变量的值传递
首先,您可以通过在tpl.Execute函数的第二个参数中指定变量来传递变量。
package main
import (
"html/template"
"log"
"os"
)
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseFiles("tpls.html"))
}
func main() {
var Age = 235
err := tpl.Execute(os.Stdout, Age) // 変数を指定
if err != nil {
log.Fatalln(err)
}
}
接下来是HTML。
要接收值,需要使用{{.}}的语法。
这是一个独特的语法,但是它是基础,请大家熟悉一下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>{{.}}</h1> <!-- 値を受け取る -->
</body>
</html>
这是执行结果。
$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>235</h1>
</body>
</html>⏎
我能看到有值被传递。
可以接收多个返回值
另外,您可以重复显示接收到的值,或将其赋值给变量。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>{{.}}</h1> <!-- 同じ値を複数回受け取る事もできる -->
<h1>{{.}}</h1>
<h1>{{$Age := .}}</h1> <!-- 代入したときは表示されない -->
<h1>{{$Age}}</h1> <!-- 値を表示 -->
</body>
</html>
$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>235</h1>
<h1>235</h1>
<h1></h1>
<h1>235</h1>
</body>
</html>⏎
传递结构体的值
接下来,传递结构体的值。
在实际开发中,最常使用结构体。
具体来说,将从JSON接收的值放入结构体中,然后进行显示等操作。
那么,我们将开始实行。
package main
import (
"html/template"
"log"
"os"
)
type Person struct {
Name string
Age int
}
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseFiles("tpls.html"))
}
func main() {
p1 := Person{
Name: "hogefuga",
Age: 28,
}
err := tpl.Execute(os.Stdout, p1)
if err != nil {
log.Fatalln(err)
}
}
这次准备了一个有两个字段的结构体,分别是姓名(Name)和年龄(Age)。
挺常规的。
这里是HTML文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>{{.}}</h1>
<h2>{{.Name}}</h2> <!-- フィールドにアクセスする -->
<h2>{{.Age}}</h2>
</body>
</html>
要访问字段,需要像{{.Name}}一样使用点(.),接着写上字段的名称。
一方面,如果只有{{.}}的话,结构体将以原样显示出来。这是直觉的体现。
以下是执行结果。
$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<h1>{hogefuga 28}</h1>
<h2>hogefuga</h2>
<h2>28</h2>
</body>
</html>⏎
这完全就是我所解释的结果。
将一个结构体切片传递
在实际开发中,如果想要使用多个hogestruct作为结构体,可能会有这样的需求。
我們也會看這個案例。
package main
import (
"html/template"
"log"
"os"
)
type Person struct {
Name string
Age int
}
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseFiles("tpls.html"))
}
func main() {
p1 := Person{
Name: "hogefuga",
Age: 28,
}
p2 := Person{
Name: "hogeeeeeee",
Age: 51,
}
p3 := Person{
Name: "fugagagaga",
Age: 3,
}
var persons = []Person{p1, p2, p3}
err := tpl.Execute(os.Stdout, persons)
if err != nil {
log.Fatalln(err)
}
}
只是传递了结构体切片。
下面是HTML代码。
要按顺序显示切片的所有元素,可以使用{{range .}}。
实际上,查看代码会更快。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<ul>
{{range .}}
<li>{{.Name}} - {{.Age}}</li>
{{end}}
</ul>
</body>
</html>
在使用range时,请确保不要忘记{{end}}。
以下是执行结果。
$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<ul>
<li>hogefuga - 28</li>
<li>hogeeeeeee - 51</li>
<li>fugagagaga - 3</li>
</ul>
</body>
</html>⏎
我认为显示正确了。
对切片中的单独元素进行访问。
顺便提一下,如果想要单独访问切片内的元素,可以在HTML中使用默认函数的索引。查看代码可能更快。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<ul>
{{index . 1}} <!-- スライスの要素に個別にアクセス -->
{{index . 2}}
{{(index . 0).Name}} <!-- 要素のフィールドにアクセスすることも可能-->
</ul>
</body>
</html>
要访问个别要素的字段,需要将其用括号{{(index . 0).Name}}括起来。
接下来是执行结果。
$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<ul>
{hogeeeeeee 51}
{fugagagaga 3}
hogefuga
</ul>
</body>
</html>
默认函数除了index还有很多其他函数。
详情请参考golang模板页的Function部分。
页面是text/template,但可以同样使用。(在html/template页面中未找到详细信息)
关于结构体的方法
在模板中,还可以执行结构体的方法。但是,方法的实现必须是值传递(指针传递会导致错误)。
package main
import (
"html/template"
"log"
"os"
)
type Person struct {
Name string
Age int
}
// func (p *Person) のようなポインタ渡しはエラーが出る
func (p Person) DoubleAge() int {
return p.Age * 2
}
var tpl *template.Template
func init() {
tpl = template.Must(template.ParseFiles("tpls.html"))
}
func main() {
p1 := Person{
Name: "hogefuga",
Age: 28,
}
err := tpl.Execute(os.Stdout, p1)
if err != nil {
log.Fatalln(err)
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
{{.DoubleAge}} <!-- methodも書き方は同じ -->
</body>
</html>
这是执行的结果。
$ go run main.go
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Golang Template Test</title>
</head>
<body>
<ul>
56
</ul>
</body>
</html>⏎
会显示Age的2倍。
最后总结
這個篇章到此結束。
我覺得此篇內容已經足夠進行基本的開發。
对于html/template,还有一些其他方法,比如传递函数给funcmap,或者使用管道|在模板中进行操作等等。如果有反馈的话,我会考虑写一篇文章。
谢谢您一直阅读到最后。