hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<!-- 嵌入动作 -->
</body>
</html>
main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
// t := template.New("hello.html")
// t, err := t.ParseFiles("hello.html")
// t := template.Must(template.ParseFiles("hello.html"))
t, err := template.ParseFiles("./hello.html")
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
}
t.Execute(w, "Hello World!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
html.template.Template
// Template is a specialized Template from "text/template" that produces a safe
// HTML document fragment.
type Template struct {
// Sticky error if escaping fails, or escapeOK if succeeded.
escapeErr error
// We could embed the text/template field, but it's safer not to because
// we need to keep our version of the name space and the underlying
// template's in sync.
text *template.Template
// The underlying template's parse tree, updated to be HTML-safe.
Tree *parse.Tree
*nameSpace // common to all associated templates
}
// Execute applies a parsed template to the specified data object,
// writing the output to wr.
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
func (t *Template) Execute(wr io.Writer, data interface{}) error {
if err := t.escape(); err != nil {
return err
}
return t.text.Execute(wr, data)
}
// Parse parses text as a template body for t.
// Named template definitions ( or statements) in text
// define additional templates associated with t and are removed from the
// definition of t itself.
//
// Templates can be redefined in successive calls to Parse,
// before the first use of Execute on t or any associated template.
// A template definition with a body containing only white space and comments
// is considered empty and will not replace an existing template's body.
// This allows using Parse to add new named template definitions without
// overwriting the main template body.
func (t *Template) Parse(text string) (*Template, error) {
if err := t.checkCanParse(); err != nil {
return nil, err
}
ret, err := t.text.Parse(text)
if err != nil {
return nil, err
}
// In general, all the named templates might have changed underfoot.
// Regardless, some new ones may have been defined.
// The template.Template set has been updated; update ours.
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
for _, v := range ret.Templates() {
name := v.Name()
tmpl := t.set[name]
if tmpl == nil {
tmpl = t.new(name)
}
tmpl.text = v
tmpl.Tree = v.Tree
}
return t, nil
}
// New allocates a new HTML template associated with the given one
// and with the same delimiters. The association, which is transitive,
// allows one template to invoke another with a action.
//
// If a template with the given name already exists, the new HTML template
// will replace it. The existing template will be reset and disassociated with
// t.
func (t *Template) New(name string) *Template {
t.nameSpace.mu.Lock()
defer t.nameSpace.mu.Unlock()
return t.new(name)
}
// Must is a helper that wraps a call to a function returning (*Template, error)
// and panics if the error is non-nil. It is intended for use in variable initializations
// such as
// var t = template.Must(template.New("name").Parse("html"))
func Must(t *Template, err error) *Template {
if err != nil {
panic(err)
}
return t
}
// ParseFiles creates a new Template and parses the template definitions from
// the named files. The returned template's name will have the (base) name and
// (parsed) contents of the first file. There must be at least one file.
// If an error occurs, parsing stops and the returned *Template is nil.
//
// When parsing multiple files with the same name in different directories,
// the last one mentioned will be the one that results.
// For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template
// named "foo", while "a/foo" is unavailable.
func ParseFiles(filenames ...string) (*Template, error) {
return parseFiles(nil, filenames...)
}
// ParseFiles parses the named files and associates the resulting templates with
// t. If an error occurs, parsing stops and the returned template is nil;
// otherwise it is t. There must be at least one file.
//
// When parsing multiple files with the same name in different directories,
// the last one mentioned will be the one that results.
//
// ParseFiles returns an error if t or any associated template has already been executed.
func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
return parseFiles(t, filenames...)
}
// ParseGlob creates a new Template and parses the template definitions from
// the files identified by the pattern. The files are matched according to the
// semantics of filepath.Match, and the pattern must match at least one file.
// The returned template will have the (base) name and (parsed) contents of the
// first file matched by the pattern. ParseGlob is equivalent to calling
// ParseFiles with the list of files matched by the pattern.
//
// When parsing multiple files with the same name in different directories,
// the last one mentioned will be the one that results.
func ParseGlob(pattern string) (*Template, error) {
return parseGlob(nil, pattern)
}
t := template.New("hello.html")
t, err :=t.ParseFiles("hello.html")
// Template is a specialized Template from "text/template" that produces a safe
// HTML document fragment.
type Template struct {
// Sticky error if escaping fails, or escapeOK if succeeded.
escapeErr error
// We could embed the text/template field, but it's safer not to because
// we need to keep our version of the name space and the underlying
// template's in sync.
text *template.Template
// The underlying template's parse tree, updated to be HTML-safe.
Tree *parse.Tree
*nameSpace // common to all associated templates
}
// Execute applies a parsed template to the specified data object,
// writing the output to wr.
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
func (t *Template) Execute(wr io.Writer, data interface{}) error {
if err := t.escape(); err != nil {
return err
}
return t.text.Execute(wr, data)
}
// ExecuteTemplate applies the template associated with t that has the given
// name to the specified data object and writes the output to wr.
// If an error occurs executing the template or writing its output,
// execution stops, but partial results may already have been written to
// the output writer.
// A template may be executed safely in parallel, although if parallel
// executions share a Writer the output may be interleaved.
func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
tmpl, err := t.lookupAndEscapeTemplate(name)
if err != nil {
return err
}
return tmpl.text.Execute(wr, data)
}
Execute方法将解析好的模板应用到data上,并输出写入wr
模板的动作是嵌入到模板的命令
:代表传递给模板的数据
要显示的内容
要显示的内容
要显示的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<!-- 嵌入动作 -->
<h1>传入了数据</h1>
<h1>未传入数据</h1>
</body>
</html>
package main
import (
"fmt"
"html/template"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("./hello.html")
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
}
// t.Execute(w, "Hello World!")
t.Execute(w, nil)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
遍历到的元素是
遍历到的元素是
没有任何元素
迭代结构体
没有任何元素
迭代Map
键是,值是
没有任何元素
迭代管道
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<!-- 嵌入动作 -->
<a href="#"></a><br/>
没有遍历到任何内容
</body>
</html>
package main
import (
"fmt"
"html/template"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("./hello.html")
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
}
stars := []struct {
Name string
Age int
}{
{Name: "马蓉", Age: 18},
{Name: "李小璐", Age: 20},
{Name: "白百合", Age: 17},
}
// stars := []string{"马蓉", "李小璐", "白百合"}
t.Execute(w, stars)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
为传过来的数据设置的新值是
为传过来的数据设置的新值是
传过来的数据仍然是
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<!-- 嵌入动作 -->
<div>得到的数据是:</div>
<div>替换之后的数据是:</div>
<hr/>
<div>看一下现在的数据是:</div>
<div>数据没有被替换,还是:</div>
</body>
</html>
package main
import (
"fmt"
"html/template"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("./hello.html")
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
}
t.Execute(w, "狸猫")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
./hello.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<!-- 嵌入动作 -->
<div>从后台得到的数据是:</div>
<!-- 包含hello2.html模板 -->
<div>hello.html文件内容结束</div>
<hr/>
<div>将hello.html模板文件中的数据传递给hello2.html模板文件</div>
</body>
</html>
./hello2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>hello2模板文件</title>
</head>
<body>
<!-- 嵌入动作 -->
<div>hello2.html模板文件中的数据是:</div>
</body>
</html>
./main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("./hello.html", "./hello2.html")
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
}
t.Execute(w, "测试包含")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
• 定义动作 定义动作达到不同网页使用相同部分,如导航栏、版权信息、联系信息等 ```
<!-- 定义模板 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
</html>
在一个模板文件中定义多个模板
./Index.html
<!-- 定义模板 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
</html>
<a href="#">点我有惊喜</a>
./main.go
package main
import (
"fmt"
"html/template"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("./index.html")
if err != nil {
fmt.Println(err)
w.WriteHeader(500)
}
t.ExecuteTemplate(w, "model", "")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
} ```
在不同模板文件中定义同名的模板
./hello.html
<!-- 定义模板 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
</body>
</html>
./content1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<h1>我是content1.html 模板文件中的内容</h1>
</body>
</html>
./content2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<h1>我是content2.html 模板文件中的内容</h1>
</body>
</html>
./main.go
package main
import (
"html/template"
"math/rand"
"net/http"
"time"
)
func handler(w http.ResponseWriter, r *http.Request) {
rand.Seed(time.Now().UnixNano())
var t *template.Template
if rand.Intn(5) > 2 {
t = template.Must(template.ParseFiles("./hello.html", "./content2.html"))
} else {
t = template.Must(template.ParseFiles("./hello.html", "./content1.html"))
}
t.ExecuteTemplate(w, "model", "")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
./hello.html
<!-- 定义模板 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
如果找不到就显示我
</body>
</html>
./content1.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板文件</title>
</head>
<body>
<h1>我是content1.html 模板文件中的内容</h1>
</body>
</html>
./main.go
package main
import (
"html/template"
"math/rand"
"net/http"
"time"
)
func handler(w http.ResponseWriter, r *http.Request) {
rand.Seed(time.Now().UnixNano())
var t *template.Template
if rand.Intn(5) > 2 {
t = template.Must(template.ParseFiles("./hello.html", "./content1.html"))
} else {
t = template.Must(template.ParseFiles("./hello.html"))
}
t.ExecuteTemplate(w, "model", "")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}