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

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

Web操作

单控制器和多控制器

单控制器
type MyHandle struct{}func(m *MyHandle)ServeHTTP(w http.ResponseWriter, r *http.Request){ fmt.Fprint(w,"返回的数据哈哈")//相当于w.Write([]byte("返回的数据哈哈"))}funcmain(){ 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("返回的数据哈哈"))}funcmain(){ h := MyHandle{} h2 := MyOtherHandle{} http.Handle("/a",&h) http.Handle("/abc",&h2) http.ListenAndServe(":8090",nil)}
2、多处理函数

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

funcfirst(w http.ResponseWriter, r *http.Request){ fmt.Fprint(w,"多处理函数--first")//相当于w.Write([]byte("返回的数据哈哈"))}funcsecond(w http.ResponseWriter, r *http.Request){ fmt.Fprint(w,"多处理函数--second")//相当于w.Write([]byte("返回的数据哈哈"))}funcmain(){ http.HandleFunc("/f", first) http.HandleFunc("/s", second) http.ListenAndServe(":8090",nil)}

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

1、获取请求头
funcnow(w http.ResponseWriter, r *http.Request){ h := r.Header fmt.Println(h) fmt.Println(h["Accept-Encoding"]) fmt.Println(len(h["Accept-Encoding"]))}funcmain(){ http.HandleFunc("/now", now) http.ListenAndServe(":9090",nil)}
2、获取请求参数
funcnow(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])}funcmain(){ 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 {returnfalse}

Web项目结构

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

HTML模版和静态资源显示

1、HTML模版显示

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

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

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

目录结构

在这里插入图片描述
2、静态资源显示

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

funcwelcome(w http.ResponseWriter, r *http.Request){ t,_:= template.ParseFiles("view/index.html") t.Execute(w,nil)}funcmain(){ http.HandleFunc("/", welcome) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) http.ListenAndServe(":9090",nil)}

目录结构

在这里插入图片描述

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

一、向模版中传递数据
  • 可以在HTML中使用{{}}获取template.Execute()第二个参数传递的值
  • 最常用的{{.}}中的".“是指针,指向当前变量,成为"dot”
1、字符串类型
funcwelcome(w http.ResponseWriter, r *http.Request){ t,_:= template.ParseFiles("view/index.html") t.Execute(w,"smallming")}funcmain(){ http.HandleFunc("/", welcome) http.ListenAndServe(":9090",nil)}
<body><pre> 尊敬的{{.}}先生/女士 您已经被我公司录取。 </pre></body>
2、结构体类型
type User struct{ Name string Age int}funcwelcome(w http.ResponseWriter, r *http.Request){ t,_:= template.ParseFiles("view/index.html") t.Execute(w, User{"张三",19})}funcmain(){ http.HandleFunc("/", welcome) http.ListenAndServe(":9090",nil)}
<body><pre> 姓名:{{.Name}}<br/> 年龄:{{.Age}} </pre></body>

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

3、map类型
type User struct{ Name string Age int}funcwelcome(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)}funcmain(){ http.HandleFunc("/", welcome) http.ListenAndServe(":9090",nil)}
<body><pre> 姓名:{{.user.Name}}<br/> 年龄:{{.user.Age}}<br/> 工资:{{.money}} </pre></body>
二、在模版中调用函数
1、调用系统函数
funcwelcome(w http.ResponseWriter, r *http.Request){ t,_:= template.ParseFiles("view/index.html") time1 := time.Now() t.Execute(w, time1)}funcmain(){ 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调用函数。

funcMyFormat(t time.Time)string{return t.Format("2006-01-02 15:04:05")}funcwelcome(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)}funcmain(){ 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"}} <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body> head.html {{.}} </body></html> {{end}} 
{{define "foot"}} <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body> foot.html {{.}} </body></html> {{end}} 
{{define "layout"}} <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><scripttype="text/javascript"src="/static/js/index.js"></script></head><body> {{/*引用head模版*/}} {{template "head" "head的参数"}}<br/> 中间内容<br/> {{template "foot" "head的参数"}} </body></html> {{end}} 

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

funcwelcome(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)}funcmain(){ http.HandleFunc("/", welcome) http.ListenAndServe(":9090",nil)}

文件上传

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

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>文件上传</title></head><body><formaction="upload"method="post"enctype="multipart/form-data"> 文件名:<inputtype="test"name="name"/><br/> 文件:<inputtype="file"name="file"/><br/><inputtype="submit"value="提交"/></form></body></html>
<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>文件上传</title></head><body> 文件上传成功 </body></html>
funcwelcome(w http.ResponseWriter, r *http.Request){ t,_:= template.ParseFiles("view/filetest.gohtml") t.Execute(w,nil)}funcupload(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)}funcmain(){ http.HandleFunc("/", welcome) http.HandleFunc("/upload", upload) http.ListenAndServe(":9090",nil)}

文件下载

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>文件上传</title></head><body><ahref="download?filename=abc.png">下载</a></body></html>
funcdownload(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)}

Read more

深入解析OpenClaw Skills:从原理到实战,打造专属机器人技能

深入解析OpenClaw Skills:从原理到实战,打造专属机器人技能

一、OpenClaw Skills:机器人行为的“最小执行单元” 1.1 什么是OpenClaw Skills? OpenClaw是面向开源机械爪/小型机器人的控制框架(核心仓库:openclaw/openclaw),旨在降低机器人行为开发的门槛。而Skills(技能) 是OpenClaw框架中对机器人“单一可执行行为”的封装模块——它将机器人完成某一特定动作的逻辑(如“夹取物体”“释放物体”“移动到指定坐标”)抽象为独立、可复用、可组合的代码单元。 简单来说: * 粒度:一个Skill对应一个“原子行为”(如“单指闭合”)或“组合行为”(如“夹取→移动→释放”); * 特性:跨硬件兼容(适配不同型号机械爪)、可插拔(直接集成到OpenClaw主框架)、可扩展(支持自定义参数); * 核心价值:避免重复开发,让开发者聚焦“

Flutter 三方库 eth_sig_util 的鸿蒙化适配指南 - 掌握以太坊加密签名核心技术、助力鸿蒙端 Web3 钱包与去中心化身份验证应用开发

Flutter 三方库 eth_sig_util 的鸿蒙化适配指南 - 掌握以太坊加密签名核心技术、助力鸿蒙端 Web3 钱包与去中心化身份验证应用开发

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 eth_sig_util 的鸿蒙化适配指南 - 掌握以太坊加密签名核心技术、助力鸿蒙端 Web3 钱包与去中心化身份验证应用开发 前言 在 OpenHarmony 鸿蒙应用的 Web3 浪潮中,安全性是应用生死存亡的关键。无论是构建非托管钱包、登录去中心化应用(dApp),还是执行 EIP-712 结构化数据的确认,都离不开严谨的以太坊签名与加密协议。eth_sig_util 作为一个专门针对以太坊签名习惯优化的 Dart 工具库,支持 personal_sign、signTypedData 以及公钥恢复等核心算法。本文将指导你如何在鸿蒙端集成 eth_sig_util,构建一套符合全球标准的加密验证体系。 一、原原理分析 / 概念介绍 1.

Windows 10/11 部署 OpenClaw 完全指南:从环境搭建到机器人互联

摘要:本文详细介绍了在 Windows x64 架构下部署开源机器人控制框架 OpenClaw 的完整流程。针对 Windows 平台特有的 C++ 编译环境难题(sharp 库依赖),提供了“一键脚本”与“手动安装”双重解决方案,并深入解析了云端大模型配置与局域网稳定连接的核心技巧,助您快速打造高性能的机器人控制中枢。 📋 前言:为什么选择 Windows 部署? OpenClaw 是一个强大的开源机器人控制框架,支持语音交互、视觉感知与大模型决策。虽然 macOS 是开发者的首选,但 Windows 10/11 (x64) 凭借广泛的硬件兼容性和强大的 GPU 生态,同样是部署 OpenClaw 的优秀平台。 核心挑战: Windows 环境下最大的痛点在于 C++ 编译环境。OpenClaw 依赖的高性能图像处理库

春晚机器人,谁赢麻了?

四家公司亮相,翻跟头和捡玻璃哪个难度更大? 马年春晚,人形机器人首次大规模登上舞台,留下的名场面足够吸睛: 二十多台机器人在聚光灯下完成Airflare大回旋七周半; 仿生机器人以1:1比例复刻蔡明的面部表情,连挑眉的细节都能同步; 轮式双臂机器人在复杂环境中自主完成捡玻璃、叠衣服等精细操作; 还有的机器人能翻桌跑酷,或是“醉倒”后迅速起身…… 图源 / 春晚微博截图 热闹亮相的背后,是四家公司不惜砸重金争夺入场券的激烈较量。松延动力、宇树科技、魔法原子、银河通用虽同为合作方,官方称谓却各有讲究:宇树是“春晚机器人合作伙伴”,松延动力为“春晚人形机器人合作伙伴”,魔法原子是“春晚智能机器人战略合作伙伴”,银河通用则称“春晚指定具身大模型机器人”。 名头的细微差别,背后对应的正是四家公司不同的技术路线与战略侧重:有人强调运动控制,有人突出仿生交互,有人主打系统集成能力,也有人押注具身大模型。 然而,当春晚落幕,越来越多人也开始思考,春晚本质上是一次高规格的“演示工程”,可以反复彩排,追求的是一次性的完美呈现,舞台成功不等于场景落地。在这场耗资不菲的高曝光豪赌中,赢得