本系列均参考https://github.com/bonfy/go-mega/blob/master/02-template-basic.md
只是为了监督自己写的博客
这里就不介绍什么是模板了,一般来说,我们使用html文件作为我们的模板文件
我们首先创建一个
类似于这样的模板
package main
import (
"html/template"
"net/http"
)
// User struct
type User struct {
Username string
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
user := User{Username: "bonfy"}
tpl, _ := template.New("").Parse(`<html>
<head>
<title>Home Page - Bonfy</title>
</head>
<body>
<h1>Hello, {{.Username}}!</h1>
</body>
</html>`)
tpl.Execute(w, &user)
})//Parse后面跟的是html文件,后文中我们将把这些代码变成一个文件,直接解析一个文件
http.ListenAndServe(":8888", nil)
}
如果对HTML文档不是很熟悉,可以看一下,我们后端的只要能大概看得懂HTML就可以了
之后我们建立一个文件夹,将静态文件都放到这个文件夹中
将模板的内容移到 static文件夹下
static/index.html
<html>
<head>
<title>Home Page - Bonfy</title>
</head>
<body>
<h1>Hello, {{.Username}}!</h1>
</body>
</html>
然后我们的main文件就变成了下面这个样子
package main
import (
"html/template"
"net/http"
)
// User struct
type User struct {
Username string
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
user := User{Username: "bonfy"}
tpl, _ := template.ParseFiles("templates/index.html")
//这里就是直接解析这个模板文件
tpl.Execute(w, &user)
})
http.ListenAndServe(":8888", nil)
}
之后我们需要学习有关模板的常用操作
模板的常用操作
条件语句
<html>
<head>
{{if .Title}}
<title>{{.Title}} - blog</title>
{{else}}
<title>Welcome to blog!</title>
</head>
<body>
<h1>Hello,{{.Username}}!</h1>
</body>
</html>
这里要去弄懂一下这个 . 是啥意思
chatgpt说
在这个HTML代码中,.Title
和.Username
是占位符,用于表示将在渲染(或填充)HTML模板时提供的实际值。通常,这些值由服务器端的后端代码生成,并通过模板引擎嵌入到HTML中,最终发送给客户端的浏览器。
.Title
和 .Username
在这里是模板中的变量,它们的值将根据后端代码的逻辑来确定。在这个例子中,.Title
用于设置页面标题,.Username
用于向用户显示其用户名。如果在渲染HTML时没有提供 .Title
的值,那么标题将默认为 "Welcome to blog!"。
就是说.后面的值通常都是后端代码提供的,所以我们发现之前的代码还缺少一个Title这个值,没有
修改main文件
package main
import (
"html/template"
"net/http"
)
type User struct {
Username string
}
type IndexxViewModel struct {
Title string
User User //嵌套结构体
}
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
user := User{
"bonfy",
}
v := IndexxViewModel{Title: "HomePage", User: user}
tpl, err := template.ParseFiles("C:\\Users\\Lenovo\\Desktop\\learn_web\\templateBasic\\static\\index.html")
if err != nil {
panic(err)
}
tpl.Execute(writer, &v)
})
http.ListenAndServe("localhost:8080", nil)
}
<html>
<head>
{{if .Title}}
<title>{{.Title}} - blog</title>
{{else}}
<title>Welcome to blog!</title>
{{end}}
</head>
<body>
<h1>Hello,{{.User.Username}}!</h1>
<!--这里.User.Username自己打的时候没有注意,就出错了-->
</body>
</html>
循环
建议大家还是把html文件还是打一下,因为你打一下会发现有些小细节会忽略
<html>
<head>
{{if .Title}}
<title>{{.Title}} - blog</title>
{{else}}
<title>Welcome to blog!</title>
{{end}}
</head>
<body>
<h1>Hello, {{.User.Username}}!</h1>
{{range .Posts}}
<div><p>{{ .User.Username }} says: <b>{{ .Body }}</b></p></div>
{{end}}
</body>
</html>
我对于html代码也不是很了解
这里将
and and
说一下:
就是一个块的意思,这里就是将内容分组,因为每个人说话就会分个组嘛,和评论一样
是段落的意思,是为了将文本组织成段落,用于排版
用来包裹用户的发表内容,使其在这个段落中显示
是加粗的意思,对结构体中Body属性进行加粗
我后面解析文件地址的时候都是引用绝对的地址,因为懒得想事情了,go程序的当前工作目录可能不是我期望的路径
每次更新html文件代码的时候,记得加{{end}}
main代码
package main
import (
"html/template"
"net/http"
)
type User struct {
Username string
}
type Post struct {
User User
Body string
}
type IndexxViewModel struct {
Title string
User User //嵌套结构体
Posts []Post
}
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
u1 := User{Username: "bofy"}
u2 := User{Username: "rene"}
posts := []Post{
{User: u1, Body: "Hardwroking..."},
{User: u2, Body: "加油努力,还有很长的路要走"},
}
v := IndexxViewModel{Title: "Homepage", User: u1, Posts: posts}
tpl, err := template.ParseFiles("C:\\Users\\Lenovo\\Desktop\\learn_web\\templateBasic\\static\\index.html")
if err != nil {
panic(err)
}
tpl.Execute(writer, &v)
})
http.ListenAndServe("localhost:8080", nil)
}
<html>
<head>
{{if .Title}}
<title>{{.Title}} - blog</title>
{{else}}
<title>Welcome to blog!</title>
{{end}}
</head>
<body>
<h1>Hello,{{.User.Username}}!</h1>
{{range .Posts}}
<div><p>{{.User.Username}} says:<b>{{.Body}}</b></p></div>
{{end}}
</body>
</html>
运行结果