传统 Web 基础操作:Go 模版引擎的极简入门指南

Web操作

单控制器和多控制器

单控制器
type MyHandle struct {
}

func (m *MyHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "返回的数据哈哈")
    //相当于w.Write([]byte("返回的数据哈哈"))
}

func main() {
    h := MyHandle{}
    server := http.Server{Addr: ":8090", Handler: &h}
    server.ListenAndServe()
    //相当于http.ListenAndServe(":8090", &h)
}
多控制器

在实际开发中,大部分情况不应该只有一个控制器,不同的请求应该交给不同的处理单元,在golang中支持两种多处理方式

  • 多个处理器(Handle)
  • 多个处理函数(HandleFunc)
1、多处理器

即使用http.Handle把不同的URL绑定到不同的处理器中

type MyHandle struct {
}
type MyOtherHandle struct {
}

func (m *MyHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "返回的数据哈哈")
    //相当于w.Write([]byte("返回的数据哈哈"))
}
func (m *MyOtherHandle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "返回的数据哈哈")
    //相当于w.Write([]byte("返回的数据哈哈"))
}

func main() {
    h := MyHandle{}
    h2 := MyOtherHandle{}
    http.Handle("/a", &h)
    http.Handle("/abc", &h2)
    http.ListenAndServe(":8090", nil)
}
2、多处理函数

把不同的URL绑定到不同的函数上

func first(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "多处理函数--first")
    //相当于w.Write([]byte("返回的数据哈哈"))
}
func second(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "多处理函数--second")
    //相当于w.Write([]byte("返回的数据哈哈"))
}

func main() {
    http.HandleFunc("/f", first)
    http.HandleFunc("/s", second)
    http.ListenAndServe(":8090", nil)
}

获取请求头和获取请求参数

1、获取请求头
func now(w http.ResponseWriter, r *http.Request) {
    h := r.Header
    fmt.Println(h)
    fmt.Println(h["Accept-Encoding"])
    fmt.Println(len(h["Accept-Encoding"]))
}

func main() {
    http.HandleFunc("/now", now)
    http.ListenAndServe(":9090", nil)
}
2、获取请求参数
func now(w http.ResponseWriter, r *http.Request) {
    r.ParseForm() //必须先解析成Form,否则无数据
    fmt.Println(r.Form)
    fmt.Println(r.Form["url_long"])
    fmt.Println(r.Form["url_long"][0])
}

func main() {
    http.HandleFunc("/now", now)
    http.ListenAndServe(":9090", nil)
}
3、验证表单的输入
//验证手机号
//使用MatchString函数和正则表达式
//其他一些字符串都可以这样判断
if m, _ := regexp.MatchString(`^(1[3|4|5|8][0-9]\d{4,8})$`, r.Form.Get("mobile")); !m {
    return false
}

Web项目结构

--项目名
	--src
	--static
		--css
		--images
		--js
	--view
		--index.html
	--main.go

HTML模版和静态资源显示

1、HTML模版显示

Go语言标准库中html/template包提供了html模版支持,把HTML当作模版可以在访问控制器显示HTML模版信息

使用template.ParseFiles()可以解析多个模版文件

func welcome(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("view/index.html")
    t.Execute(w, nil)
}

func main() {
    http.HandleFunc("/", welcome)
    http.ListenAndServe(":9090", nil)
}

目录结构

在这里插入图片描述

2、静态资源显示

把静态资源文件放到特定的文件夹中,使用Go语言的文件服务就可以进行加载

func welcome(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("view/index.html")
    t.Execute(w, nil)
}

func main() {
    http.HandleFunc("/", welcome)
    http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))
    http.ListenAndServe(":9090", nil)
}

目录结构

在这里插入图片描述

向模版中传递数据和调用函数

一、向模版中传递数据
  • 可以在HTML中使用{{}}获取template.Execute()第二个参数传递的值
  • 最常用的{{.}}中的".“是指针,指向当前变量,成为"dot”
1、字符串类型
func welcome(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("view/index.html")
    t.Execute(w, "smallming")
}

func main() {
    http.HandleFunc("/", welcome)
    http.ListenAndServe(":9090", nil)
}
<body>
<pre>
    尊敬的{{.}}先生/女士
        您已经被我公司录取。
</pre>
</body>
2、结构体类型
type User struct {
	Name string
	Age  int
}

func welcome(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("view/index.html")
    t.Execute(w, User{"张三", 19})
}

func main() {
    http.HandleFunc("/", welcome)
    http.ListenAndServe(":9090", nil)
}
<body>
<pre>
    姓名:{{.Name}}<br/>
    年龄:{{.Age}}
</pre>
</body>

PS:结构体的字段一定要首字母大写,否则模版访问不到。

3、map类型
type User struct {
    Name string
    Age  int
}

func welcome(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("view/index.html")
    m := make(map[string]interface{})
    m["user"] = User{"张三", 19}
    m["money"] = 1000
    t.Execute(w, m)
}

func main() {
    http.HandleFunc("/", welcome)
    http.ListenAndServe(":9090", nil)
}
<body>
<pre>
    姓名:{{.user.Name}}<br/>
    年龄:{{.user.Age}}<br/>
    工资:{{.money}}
</pre>
</body>
二、在模版中调用函数
1、调用系统函数
func welcome(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("view/index.html")
    time1 := time.Now()
    t.Execute(w, time1)
}

func main() {
    http.HandleFunc("/", welcome)
    http.ListenAndServe(":9090", nil)
}
<body>
<pre>
完整时间:{{.}}
年:{{.Year}}
月:{{.Month}}
日:{{.Day}}
格式化时间:{{.Format "2006-01-02 15:04:05"}}
</pre>
</body>
2、调用自定义函数

如果希望调用自定义函数,需要借助html/template包下的FuncMap进行映射。

函数被添加映射后,只能通过函数在FuncMap中的key调用函数。

func MyFormat(t time.Time) string {
    return t.Format("2006-01-02 15:04:05")
}

func welcome(w http.ResponseWriter, r *http.Request) {
    //将自定义函数绑定到map上
    fm := template.FuncMap{"mf": MyFormat}
    //新建一个空模版,将函数绑定到该模版
    t := template.New("index.html").Funcs(fm)
    //把我们的html解析到该空模版上
    t, _ = t.ParseFiles("view/index.html")
    time1 := time.Now()
    t.Execute(w, time1)
}

func main() {
    http.HandleFunc("/", welcome)
    http.ListenAndServe(":9090", nil)
}
<body>
<pre>
完整时间:{{.}}
调用格式化函数:{{mf .}}
</pre>
</body>

模版使用if、range等

1、二元比较运算函数
eq  <=>	 ==
ne	<=>	 !=
lt	<=>	 <
le	<=>	 <=
gt	<=>	 >
ge	<=>	 >=
2、if语句
<body>
取出数据{{.}}<br/>
{{if .}}
    执行了if
{{else}}
    执行了else
{{end}}<br/>
html模版信息
</body>
<body>
    {{$n:=123}}
    {{if gt $n 456}}
        执行if
    {{else}}
        执行else
    {{end}}
</body>
3、range的使用
<body>
    {{.}}<br/>
    {{range .}}
        {{.}}<br/>
    {{end}}
</body>

模版嵌套

  • 在实际项目中常常出现页面复用的情况,例如:整个网站的头部信息和底部信息复用

  • 可以使用动作{{template “模版名称”}}来引用模版

  • 引用的模版必须在HTML中定义这个模版

定义名称

{{define "模版名称"}}
html
{{end}}

示例:

{{define "head"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
head.html {{.}}
</body>
</html>
{{end}}
{{define "foot"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
foot.html {{.}}
</body>
</html>
{{end}}
{{define "layout"}}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script type="text/javascript" src="/static/js/index.js"></script>
</head>
<body>
{{/*引用head模版*/}}
{{template "head" "head的参数"}}<br/>
中间内容<br/>
{{template "foot" "head的参数"}}
</body>
</html>
{{end}}

在go中需要加载所有文件再选定主模版

func welcome(w http.ResponseWriter, r *http.Request) {
    //解析所有文件
    t, err := template.ParseFiles("view/index.gohtml", "view/head.gohtml", "view/foot.gohtml")
    if err != nil {
       log.Printf("err:%v", err)
    }
    //选定主模版layout
    t.ExecuteTemplate(w, "layout", nil)
}

func main() {
    http.HandleFunc("/", welcome)
    http.ListenAndServe(":9090", nil)
}

文件上传

文件中ioutil包已经弃用,这里使用io包和os包

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
    文件名:<input type="test" name="name"/><br/>
    文件:<input type="file" name="file"/><br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
    文件上传成功
</body>
</html>
func welcome(w http.ResponseWriter, r *http.Request) {
    t, _ := template.ParseFiles("view/filetest.gohtml")
    t.Execute(w, nil)

}

func upload(w http.ResponseWriter, r *http.Request) {
    //从表单中获取名为"name"的值
    fileName := r.FormValue("name")
    //从表单中获取名为"file"的文件字段
    //file是文件句柄
    //fileHeader是文件的元信息,包括文件名、大小等
    file, fileHeader, _ := r.FormFile("file")
    //读取文件中的内容
    b, _ := io.ReadAll(file)
    os.WriteFile("D:/"+fileName+fileHeader.Filename[strings.LastIndex(fileHeader.Filename, "."):], b, 0777)
    t, _ := template.ParseFiles("view/success.gohtml")
    t.Execute(w, nil)
}

func main() {
    http.HandleFunc("/", welcome)
    http.HandleFunc("/upload", upload)
    http.ListenAndServe(":9090", nil)
}

文件下载

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件上传</title>
</head>
<body>
<a href="download?filename=abc.png">下载</a>
</body>
</html>
func download(w http.ResponseWriter, r *http.Request) {
    //从表单中获取文件名称
    filename := r.FormValue("filename")
    //根据路径去找文件
    f, err := os.ReadFile("D:/" + filename)
    if err != nil {
        
       fmt.Fprintln(w, "文件下载失败", err)
       return
    }

    h := w.Header()
    //设置相应内容的MIME类型魏二进制流
    //设置为文件处理,而不是直接显示
    h.Set("Content-Type", "application/octet-stream")
    //attachment设置内容处置方式为附件下载
    //filename="..."指定下载时的默认文件名filename
    h.Set("Content-Disposition", "attachment;filename="+filename)
    //将文件内容写入http响应体发送
    w.Write(f)
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值