この記事を読んでわかること
- ネストされた構造体のスライスの中身をhtmlに表示させるための書き方
- 実際に実装してみるためのサンプルコード
サンプルコード(main.go, template.html)
先にサンプルコードを示しておく。今回はmain.goファイルとtemplate.htmlを使用する。Pathについては各自改めて設定していただきたい。
package main
import (
"html/template"
"net/http"
"log"
)
type User struct {
ID int
Name string
Email string
Todos []Todo
}
type Todo struct {
Title string
Content string
Done bool
}
func generateHTML(w http.ResponseWriter, data interface{}) {
tmpl := template.Must(template.ParseFiles("templates/template.html"))
err := tmpl.Execute(w, data)
if err != nil {
log.Println(err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
user := User{
ID: 1,
Name: "John Doe",
Email: "john@example.com",
}
todo1 := Todo{
Title: "Task 1",
Content: "Do task 1",
Done: false,
}
todo2 := Todo{
Title: "Task 2",
Content: "Do task 2",
Done: true,
}
user.Todos = append(user.Todos, todo1)
user.Todos = append(user.Todos, todo2)
generateHTML(w, user)
})
log.Println("Server started on localhost:8080")
http.ListenAndServe(":8080", nil)
}
<!DOCTYPE html>
<html>
<head>
<title>User Information</title>
</head>
<body>
<h1>User Information</h1>
<p>ID: {{ .ID }}</p>
<p>Name: {{ .Name }}</p>
<p>Email: {{ .Email }}</p>
<h2>Address</h2>
{{ range .Todos}}
<p>Title: {{ .Title }}</p>
{{end}}
</body>
</html>
設定の確認
構造体について確認しておく。
type User struct {
ID int
Name string
Email string
Todos []Todo
}
type Todo struct {
Title string
Content string
Done bool
}
ここではUserという構造体とTodoという構造体を定義している。
Userという構造体には、ID, Name, Email, Todosというフィールドが存在していることがわかる。
ただTodosがスライス型であることに注意していただきたい。
また、Todoという構造体には、Title, Content, Doneというフィールドが存在する。
user := User{
ID: 1,
Name: "Tarou",
Email: "Tarou@example.com",
}
todo1 := Todo{
Title: "Task 1",
Content: "Do task 1",
Done: false,
}
todo2 := Todo{
Title: "Task 2",
Content: "Do task 2",
Done: true,
}
user.Todos = append(user.Todos, todo1)
user.Todos = append(user.Todos, todo2)
ここでは、TarouのTodoを2つ作成している。
そして、main.goファイルで
generateHTML(w, user)
このように書いたことでuser、つまりTarouの情報がhtmlに渡されている。
本題
ここでやりたいことはTarouのTodosの中のTitleを並べて表示するということである。
そこで使用するのがrangeである。
htmlの中で以下のように指定する。
{{ range .Todos }}
<p>Title: {{ .Title }}</p>
{{end}}
{{ range .Todos }}と{{end}}で括った部分がTodosの長さ分繰り返される。
そして、特に注意しなければならないのがTitleの取り出し方である。
一般的にネストされた構造体の中身を見るときは、
{{ .Todos.Title }}
とすることで確認することができるが、rangeを使う場合はその中で.Todosは不要になり、
{{ .Title }}
のみで使用することになる。
私はそれがわからず数時間悪戦苦闘することになってしまったが、皆さんはそのようなことがないことを祈っている。
最後に
初めてのQiita記事で読みにくいところがあったかもしれませんが、最後まで読んでいただきありがとうございました。