赞
踩
源代码路径:chapter03\test_syntax_tpl.go
模板路径:template\chapter03\test.html
1.字符串:{ { “zhiliao ” } }
2.原始字符串:{ { zhiliao
} } 不会转义
3.字节类型:{ { ’ a’ } } -->97 ascll码对应表: http://ascii.911cha.com/
4.nil类型:{ { print nil } } { {nil } }只有nil会报错:nil is not a command
1.定义:
{{$username := "xxxx"}}
2.使用:
{{$username }}
注意:只能在当前模板中使用
1.可以是上下文的变量输出,也可以是函数通过管道传递的返回值
e.g.
1.if…else
{{if .name}}
有姓名
{{else}}
没有姓名
{{end}}
2.if嵌套
成年人而且带了身份证的准进:
{{if .A}}
{{if .C }}
可以进
{{else}}
不能进
{{end}}
{{else}}
未成年不能进
{{end}}
第一种: {{range $v := .arr_struct}} {{$v.Name}} {{$v.Age}} {{$v.Gender}} {{end}} 下面的也可以 {{range $v := .arr}} {{/*{{$v}}*/}} {{.}} {{end}} 第二种: {{ range .arr_struct }} {{.Name }} {{.Age}} {{ $.total}} // 使用 $. 引用模板中的根级上下文 {{end}}
range也支持else,当长度为0时,执行else
{{range .total}}
{{.}}
{{else}}
{{ 0 }} {{/* 当 .total 为空 或者 长度为 0 时会执行这里 */}}
{{end}}
1.作用:用于重定向 pipeline
2.使用
{{with .user}}
{{.Id}}
{{.Name}}
{{end}}
不用每个字段前面都加user.了
3.支持else,当长度为0时,显示else中的数据
{{with .user}}
{{.Id}}
{{.Name}}
{{else}}
暂无数据
{{end}}
场景:登录的用户显示用户名,没有登录的用户显示"游客"
1.作用:引入另一个模板文件,对于模板的分模块处理很有用处,
2.使用:{ {template “模板名” pipeline} }
e.g.
{{template "user/test.html" .}}
注意:
允许多行文本注释,不允许嵌套
{{/* comment content
support new line */}}
{{/*
这是模板块注释
这是模板块注释
这是模板块注释
这是模板块注释
*/}}
源代码路径:chapter03\test_func_tpl.go
模板路径:template\chapter03\terst_func_tpl.html
print:对应 fmt.Sprint
printf:对应 fmt.Sprintf
println:对应 fmt.Sprintln
{{print "hallen"}}
fmt.Sprint和fmt.Print的区别:
变量可以使用符号 | 在函数间传递
{{.Name | printf "%s"}}
{{printf "nums is %s %d" (printf "%d %d" 1 2) 3}}
{{printf "name:%s,addr:%s" "hallen" (printf "%s-%s" "北京市" "西城区")}}
1.作用:只要有一个为空,则整体为空,如果都不为空,则返回最后一个
2.使用:
{{and .X .Y .Z}}
1.作用:只要有一个不为空,则返回第一个不为空的,否则返回空
2.使用:
{{or .X .Y .Z}}
1.作用:可以调用函数,并传入参数
2.使用:
{{call .Field .Arg1 .Arg2}}
1.作用:读取指定类型对应下标的值
2.支持 map, slice, array, string
e.g.
数据准备:
arr := []int{1,2,3,4,5}
message := map[string]interface{}{
"arr":arr,
"name":map[string]interface{}{"name":"xx111","age":18},
}
使用:
{{index .name "name"}}
{{index .arr 1}}
注意:数组的角标从0开始的
1.作用:返回对应类型的长度
2.支持类型:map, slice, array, string, chan
e.g.
{{.arr | len}}
1.作用:返回输入参数的否定值
2.使用
{{not .arr1}}
1.作用:有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了。
2.使用
{{urlquery "http://www.baidu.com"}}
结果:http%3A%2F%2Fwww.baidu.com
% 后面的就是字符的16进制的字符码
1.eq:等于
2.ne:不等于
3.lt:小于 less
4.le:小于等于
5.gt:大于 greater
6.ge:大于等于
{{eq .num 18}}
{{ne .num 17}}
{{lt .num 16}}
{{le .num 18}}
{{gt .num 18}}
{{ge .num 18}}
eq 和其他函数不一样的地方是,支持多个参数
{{eq .num 10 11 17 18}}
1.实现了时间的格式化,返回字符串,也可以在后端转好,前端直接使用
2.使用方法
使用方法 { {.time_data.Format “2006/01/02 15:04:05”} }
设置时间格式比较特殊,需要按如下方式,一定不能变
和go语言的使用方法类似
now := time.Now().Format("2006/01/02 15:04:05")
二、html
1.作用:转义文本中的html标签
如将“<”转义为“<”,“>”转义为“>”等
三、js
1.作用:返回用JavaScript的escape处理后的文本
escape函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串
可以使用unescape解吗
{{js "<script>xx</script>"}}
结果:\x3Cscript\x3Exx\x3C/script\x3E
模板函数整理
var builtins = FuncMap{ "and": and, "call": call, "html": HTMLEscaper, "index": index, "js": JSEscaper, "len": length, "not": not, "or": or, "print": fmt.Sprint, "printf": fmt.Sprintf, "println": fmt.Sprintln, "urlquery": URLQueryEscaper, // Comparisons "eq": eq, // == "ge": ge, // >= "gt": gt, // > "le": le, // <= "lt": lt, // < "ne": ne, // != }
func SubStr(str string,l int) string {
ret := str[0:l]
return (ret + "...")
}
engine.SetFuncMap(template.FuncMap{
"SubStr": SubStr, // 字符串名称是前端使用的名称
})
{{SubStr "qwertyuu" 3}}
注意:是左闭右开区间
Gin提供了两类绑定方法:
Bind
,BindJSON
,BindXML
,BindQuery
,BindYAML
MustBindWith
的具体调用。 如果发生绑定错误,则请求终止,并触发 c.AbortWithError(400, err).SetType(ErrorTypeBind)
。响应状态码被设置为 400 并且Content-Type
被设置为text/plain; charset=utf-8
。 如果您在此之后尝试设置响应状态码,Gin会输出日志[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422
。 如果您希望更好地控制绑定,考虑使用ShouldBind
等效方法。ShouldBind
,ShouldBindJSON
,ShouldBindXML
,ShouldBindQuery
,ShouldBindYAML
ShouldBindWith
的具体调用。 如果发生绑定错误,Gin 会返回错误并由开发者处理错误和请求。可以绑定Form、QueryString、Json,uri
form标签:Form、QueryString
json标签:Json
uri标签:uri
form的绑定示例代码:
// 结构体 type User struct { Id int `form:"id" json:"id"` Name string `form:"name" json:"name"` } // 注意:structTag:指定字段名称,不用使用首字母大写的 // 绑定 var user User context.ShouldBind(&user) fmt.Println(user) // 前端 <form action="/dobind" method="post"> <input type="text" name="name"><br> <input type="text" name="age"><br> <input type="submit" value="提交"> </form>
QueryString的绑定示例代码:
// 结构体中structTag的form起作用
var user User
context.ShouldBind(&user)
fmt.Println(user)
访问:http://127.0.0.1:8080/tobind?name=zhiliao&age=110
json的绑定示例代码
// 结构体中structTag的json起作用 func DoBind(context *gin.Context) { var user User context.ShouldBind(&user) fmt.Println(user) context.JSON(200,gin.H{ "msg":"success", "code":200, }) } 前端:ajax <form> <input type="text" name="name" id="name"><br> <input type="text" name="age" id="age"><br> <input type="button" value="提交" id="btn_add"> </form> <script> var btn_add = document.getElementById("btn_add"); btn_add.onclick = function (ev) { var name = document.getElementById("name").value; var age = document.getElementById("age").value; $.ajax({ url:"/dobind", type:"POST", contentType: "application/json; charset=utf-8", dataType: "json", data:JSON.stringify({ "name":name, "age":Number(age) }), success:function (data) { console.log(data); }, fail:function (data) { console.log(data); } }) } </script> 注意: contentType: "application/json; charset=utf-8", dataType: "json", "age":Number(age) age是个int类型,必须得转成int类型才可以直接绑定
可以使用显式绑定声明绑定 multipart form:
c.ShouldBindWith(&form, binding.Form)
或者简单地使用 ShouldBind 方法自动绑定
ShouldBindJSON,ShouldBindXML,ShouldBindQuery,ShouldBindYAML等函数只绑定对应格式的参数
使用structTag:uri
// 结构体中structTag的uri起作用 结构体: type User struct { Id int `uri:"id"` Name string `uri:"name"` Age int `uri:"age"` } 路由:engine.GET("/tobind2/:name/:age",ToBind) func ToBind(context *gin.Context) { var user User context.ShouldBindUri(&user) fmt.Println(user) context.String(200,"success") } 访问:http://127.0.0.1:8080/tobind2/zhiliao/110
可以绑定Form、QueryString、Json等
和ShouldBind的区别在于,ShouldBind没有绑定成功不报错,就是空值,Bind会报错
BindJSON,BindXML,BindQuery,BindYAML等函数只绑定对应格式的参数
go-playground/validator.v8进行验证
使用structTag的binding,如:binding:“required”
如果没有空值或者类型不匹配就会报错,重定向到400 (Bad Request)
错误信息:Key: ‘User.Name’ Error:Field validation for ‘Name’ failed on the ‘required’ tag
示例代码:
type User struct { Id int `form:"id"` Name string `form:"name" binding:"required"` // 不为空校验 Age int `form:"age"` } func DoBind(context *gin.Context) { var user User err := context.ShouldBind(&user) if err != nil { fmt.Println(err) context.JSON(400,gin.H{ "msg":"fali", "code":400, }) } context.JSON(200,gin.H{ "msg":"success", "code":200, }) }
注意:
多个验证器之间用英文输入法下的逗号(,)隔开,并且是按照验证器的顺序执行的
如果希望在参数中包含逗号(即excludesall =,),则需要使用UTF-8十六进制表示形式0x2C
e.g.
validate:"excludesall=0x2C"
1.- 忽略字段,如:binding:“-”
2.required: 必填字段,如:binding:“required”
3.min 最小长度,如:binding:“min=10”
4.max 最大长度,如:binding:“max=10”
5.| 或,如:binding:“rgb|rgba”
6.structonly 如果有嵌套,可以决定只验证结构体上的,binding:“structonly”
7.Exists
8.omitempty 省略空,如果为空,则不会继续验证该字段上其他的规则,只有不为空才会继续验证其他的,如max等
9.dive 嵌套验证
1.name [][]string `binding:"gt=0,dive,len=1,dive,required"`
// gt = 0将应用于[]
// len = 1将应用于[] string
//必填项将应用于字符串
2.name [][]string `binding:"gt=0,dive,dive,required"`
// gt = 0 将应用于[]
// []string 将保留验证
//必填项将应用于字符串
10.len 长度,如:binding:“len=10”
11.eq 等于,如:binding:“eq=10”
12.ne 不等于,如:binding:“ne=10”
13.gt 大于,如:binding:“gt=10”
14.gte 大于等于,如:binding:“gte=10”
15.lt 小于,如:binding:“lt=10”
16.lte 小于等于,如:binding:“lte=10”
注意:gt、gte、lt、lte等都可以用于时间的比较,后面不需要跟值,直接binding:“gt”,表示大于当前utc时间
17.eqfield 等于其他字段的值,如:Password string binding:"eqfield=ConfirmPassword"
18.nefield 不等于其他字段的值,
19.eqcsfield 类似eqfield,它会验证相对于顶层结构提供的字段,
如:eqcsfield = InnerStructField.Field)
20.necsfield
21.gtfield 大于其他字段的值
22.gtefield
23.gtcsfield
24.gtecsfield
25.ltfield 小于其他字段的值
26.ltefield
27.ltcsfield
28.ltecsfield
29.alpha 字符串值仅包含字母字符
30.alphanum 字符串值仅包含字母数字字符
31.numeric 字符串值包含基本数字值。基本不包括指数等…
32.hexadecimal 字符串值包含有效的十六进制
33.hexcolor 验证字符串值包含有效的十六进制颜色,包括井号(#)
34.rgb 字符串值包含有效的rgb颜色
35.rgba 字符串值包含有效的rgba颜色
36.HSL 字符串值包含有效的hsl颜色
37.hsla 字符串值包含有效的hsla颜色
38.email 字符串值包含有效的电子邮件
39.url 字符串值包含有效的网址,必须包含http://等
40.uri 字符串值包含有效的uri。它将接受golang请求uri接受的任何uri
41.base64 字符串值包含有效的base64值
42.contains 字符串值包含子字符串值,contains=@
43.containsany 包含所有,containsany =!@#?
44.containsrune 字符串值包含提供的符号 containsrune = @
45.excludes 字符串值不包含子字符串值,excludes = @
46.excludeall 排除所有
47.excluderune 字符串值不包含提供的符号,excluderune = @
48.isbn 国际标准书号,验证字符串值包含有效的isbn10或isbn13值。
49.isbn10 国际标准书号10, 验证字符串值包含有效的isbn10值。
50.isbn13 国际标准书号13,字符串值包含有效的isbn13值。
51.uuid 字符串值包含有效的UUID。
52.uuid3 字符串值包含有效的版本3 UUID
53.uuid4 字符串值包含有效的版本5 UUID。
54.uuid5 字符串值包含有效的版本5 UUID。
55.ascii 字符串值仅包含ASCII字符。注意:如果字符串为空,则验证为true。
56.asciiprint 字符串值仅包含可打印的ASCII字符。注意:如果字符串为空,则验证为true。
57.multibyte 字符串值包含一个或多个多字节字符。注意:如果字符串为空,则验证为true。
58.datauri 字符串值包含有效的DataURI。注意:这还将验证数据部分是有效的base64
59.latitude 纬度,字符串值包含有效的纬度
60.longitude 经度,字符串值包含有效的经度。
61.ssn 字符串值包含有效的美国社会安全号码
62.ip 字符串值包含有效的IP地址
63.ipv4 字符串值包含有效的v4 IP地址。
64.ipv6 字符串值包含有效的v6 IP地址。
65.cidr 字符串值包含有效的CIDR地址。
66.cidrv4 字符串值包含有效的CIDR地址。
67.cidrv6 字符串值包含有效的v6 CIDR地址。
68.tcp_addr 字符串值包含有效的可解析TCP地址。
…
max,len,min:
官方文档:
https://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Baked_In_Validators_and_Tags
https://gin-gonic.com/zh-cn/docs/examples/custom-validators/
go get github.com/go-playground/validator
1.定义验证器
var Len6Valid validator.Func = func(fl validator.FieldLevel) bool {
data := fl.Field().Interface().(string)
if len(data) > 6 {
fmt.Println("false")
return false
}else {
fmt.Println("true")
return true
}
}
注意:必须为validator.Func类型
2.注册验证器
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("len_valid", valid.Len6Valid)
}
在路由匹配前,main中即可
3.结构体中使用
type Article struct {
Id int `form:"id"`
Title string `form:"title" binding:"required,len_valid"`
Desc string `form:"desc" binding:"required,len_valid"`
}
这里必须binding中,而且名称为前面注册的字符串名称
go get github.com/astaxie/beego/validation
type LoginParams struct { Name string valid:"Required" Age int valid:"Required;MinSize(2)" Addr string valid:"Required" } func (l *LoginController) Post() { valid := validation.Validation{} // 解析到结构体 params := LoginParams{} if err := l.ParseForm(¶ms); err != nil { //handle error return } //重写错误信息:validation.SetDefaultMessage(map) var messages = map[string]string{ "Required": "不能为空", "MinSize": "最短长度为 %d", "Length": "长度必须为 %d", "Numeric": "必须是有效的数字", "Email": "必须是有效的电子邮件地址", "Mobile": "必须是有效的手机号码", } validation.SetDefaultMessage(messages) // 校验 b, err := valid.Valid(¶ms) // 验证StructTag 是否正确 if err != nil { fmt.Println(err) } if !b { // 验证没通过,则b为false for _, err := range valid.Errors { fmt.Println(err.Key, err.Message) message := err.Key + err.Message l.Ctx.WriteString(message) } } }
https://gin-gonic.com/zh-cn/docs/examples/grouping-routes/
v1 := engine.Group("/v1")
v2 := engine.Group("/v2")
{
v1.GET("/tobind", ToBind)
v1.GET("/hello3", Hello3)
}
{
v2.GET("/my_valid", valid.MyValid)
}
1.main.go中
"gin_test_project/routers"
router := gin.Default()
routers.Routers(router) // routers是总路由的package名称
2.总路由
package routers
import (
"github.com/gin-gonic/gin"
"gin_test_project/valid"
)
func Routers(router *gin.Engine) {
valid_router := router.Group("/v1")
valid.Routers(valid_router) // valid是项目中的valid模块package名称
}
3.模块路由
package valid
import (
"github.com/gin-gonic/gin"
)
func Routers(valid_router *gin.RouterGroup) {
{
valid_router.GET("/my_valid", MyValid)
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。