使用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,或者使用管道|在模板中进行操作等等。如果有反馈的话,我会考虑写一篇文章。

谢谢您一直阅读到最后。

bannerAds