The author's small station: Qiuma record
Noncommittal, Hugo
the template
same is golang
the standard library used html/template
. In order to realize a unique theme of your own Hugo theme
, or to modify other people's themes, you have to 模板语法
know about it, so that you can change it to your heart's content, or create a set that is both simple and elegant Hugo theme
.
Create a golang project
Obviously, we must first create a golang
project before we can explain what is golang
going on html/template
. There is no doubt about this. After all, what we are playing now golang
is golang
the standard library html/template
.
Alright, enough gossip, let's get to the point. About golang
how to create a project, you should be relatively clear! Otherwise, you will not browse this article, of course, you can't say that! Maybe he just wants to understand golang
the syntax of templates so that he can develop Hugo theme
, which is true.
For how to configure the golang
relevant module
properties, you can check the previous articles. This article will not go into details, but will focus on explaining html/template
the syntax.
You can create a project by typing the following command in any empty file on your computer cmd
(that is, the command line).
go mod init template.qiucode.cn #其中 template.qiucode.cn 是您项目模块名称,您可以起个响亮的名字,以便符合您的气质!(纯属笑谈)
Create a new file in the current directory main.go
and type the following code:
package main
import (
"log"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", home)
mux.HandleFunc("/blog/view", snippetView)
mux.HandleFunc("/blog/create", snippetCreate)
log.Print("Starting server on :4000")
err := http.ListenAndServe(":4000", mux)
log.Fatal(err)
}
We piled up the original request processing method in main.go
the file and extracted it into a new file. Then you need to create a new handlers.go
file. As for the content, it is as follows:
package main
import (
"fmt"
"net/http"
"strconv"
)
func home(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
w.Write([]byte("Hello from Snippetbox"))
}
func snippetView(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(r.URL.Query().Get("id"))
if err != nil || id < 1 {
http.NotFound(w, r)
return
}
fmt.Fprintf(w, "Display a specific snippet with ID %d...", id)
}
func snippetCreate(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.Header().Set("Allow", http.MethodPost)
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
return
}
w.Write([]byte("Create a new snippet..."))
}
template composition
Create a template file in the current folder home.tmpl
, and the file path is as follows.
<!doctype html>
<html lang='zh'>
<head>
<meta charset='utf-8'>
<title>首页</title>
</head>
<body>
<header>
<h1><a href='/'>这是头部</a></h1>
</header>
<main>
<h2>主体部分s</h2>
<p>写点什么吧!</p>
</main>
<footer>Powered by <a href='https://golang.org/'>Go</a></footer>
</body>
</html>
Go back to handlers.go
the file and modify its home
handler function.
package main
import (
"fmt"
"html/template" // 新添加
"log" // 新添加
"net/http"
"strconv"
)
func home(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
//解析模板文件
ts, err := template.ParseFiles("./ui/html/pages/home.tmpl")
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", 500)
return
}
err = ts.Execute(w, nil)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", 500)
}
}
//... 省略其他方法
It is true that there will be more *.tmpl
files in the folder, how to share the public content such as the header, sidebar, and bottom with other pages? In order to eliminate redundant content, all template files will include base.tmpl
files.
{
{define "base"}}
<!doctype html>
<html lang='zh'>
<head>
<meta charset='utf-8'>
<title>{
{template "title" .}} - 秋码记录</title>
</head>
<body>
<header>
<h1><a href='/'>这是头部</a></h1>
</header>
<main>
{
{template "main" .}}
</main>
<footer>Powered by <a href='https://golang.org/'>Go</a></footer>
</body>
</html>
{
{end}}
{
{define "base"}}...{
{end}}
Action to define a template named base
, which contains the content we want to appear on each page. Internally, we use {
{template "title" .}}
the and operator to indicate that we want to call other named templates (called and ) {
{template "main" .}}
at specific locations .title
main
Let's modify ui/html/pages/home.tmpl
the contents of the file.
{
{define "title"}}Home{
{end}}
{
{define "main"}}
<h2>这是主体</h2>
<p>说点什么吧!</p>
{
{end}}
Of course, we have to modify the processing function handlers.go
in home
.
package main
import (
"fmt"
"html/template" // 新添加
"log" // 新添加
"net/http"
"strconv"
)
func home(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
files := []string{
"./ui/html/base.tmpl",
"./ui/html/pages/home.tmpl",
}
ts, err := template.ParseFiles(files...)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", 500)
return
}
err = ts.ExecuteTemplate(w, "base", nil)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", 500)
}
}
//... 省略其他方法
So now, instead of directly containing HTML, our template set contains 3 named templates — base
, , title
and main
. We use ExecuteTemplate()
methods to tell Go
us exactly what base
content we want to use in response (which in turn calls our title
and main
templates).
template embedding
We want certain content to be abstracted and reused across different pages or layouts.
To illustrate this, let's create a navbar with the following sections.
{
{define "nav"}}
<nav>
<a href='/'>首页</a>
</nav>
{
{end}}
At the same time, modify ui/html/base.tmpl
the file.
{
{define "base"}}
<!doctype html>
<html lang='zh'>
<head>
<meta charset='utf-8'>
<title>{
{template "title" .}} - 秋码记录</title>
</head>
<body>
<header>
<h1><a href='/'>这是头部</a></h1>
</header>
{
{template "nav" .}}
<main>
{
{template "main" .}} {
{/*添加了这一行内容*/}}
</main>
<footer>Powered by <a href='https://golang.org/'>Go</a></footer>
</body>
</html>
{
{end}}
Of course, the processing function handlers.go
in the file home
has to be modified accordingly.
package main
import (
"fmt"
"html/template" // 新添加
"log" // 新添加
"net/http"
"strconv"
)
func home(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
files := []string{
"./ui/html/base.tmpl",
"./ui/html/partials/nav.tmpl", //添加这一行内容
"./ui/html/pages/home.tmpl",
}
ts, err := template.ParseFiles(files...)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", 500)
return
}
err = ts.ExecuteTemplate(w, "base", nil)
if err != nil {
log.Print(err.Error())
http.Error(w, "Internal Server Error", 500)
}
}
//... 省略其他方法
block
As you also saw above, the {
{template}}
. In fact, golang
we also provide another, that is, Hugo·``中常用的
{
{block}} ... {
{end}}``` operation.
For example:
{
{define "base"}}
<h1>An example template</h1>
{
{block "sidebar" .}}
<p>My default sidebar content</p>
{
{end}}
{
{end}}
You don't need {
{block}}
to include any default content and {
{end}}
actions in between. In this case, the called template is like "optional". If the template exists in the template set, it will be rendered. But if you don't, then nothing is displayed.
The author's small station: Qiuma record