学习 Gin 问题总结 2020.12.29

学习 Gin 问题总结 2020.12.29 数据绑定与解析 BindXXX,ShouldBindXXX和ShouldBindWith区别

BindXXX

会自动返回信息,输入无效时,在header写入400

ShouldBindXXX

返回消息,输入无效时,不会在header写入400状态码,这时候可以自定义返回信息,在使用上相对来说更加灵活。

ShouldBindWith

在gin 1.4 之前,重复使用ShouldBind绑定会报错EOF。

gin 1.4 之后官方提供了一个 ShouldBindBodyWith 的方法,可以支持重复绑定,原理就是将body的数据缓存了下来,但是二次取数据的时候还是得用 ShouldBindBodyWith 才行,直接用 ShouldBind 还是会报错的。

根据方法内参数b的类型去绑定json,query,去绑定obj,不返回状态码。

func (c *Context) ShouldBindWith(obj interface{}, b binding.Binding) error { return b.Bind(c.Request, obj) } HTML渲染 func main() { // 1.创建路由 r := gin.Default() //静态文件,声明模板文件所在的目录,系统自动解析 r.LoadHTMLGlob("static/html/*") ... }

LoadHTMLGlob(),该方法参数内的目录下,不能有二级目录,存在二级目录将会panic。

而且该方法只能在一个实例中对一个目录使用一次(使用过的目录下的子目录同样是为已使用)。

使用两次

//静态文件,声明模板文件所在的目录,系统自动解析 r.LoadHTMLGlob("static/html/*") r.LoadHTMLGlob("static/html/html2/*")

将会:

panic: read static\html\html2: The handle is invalid.

如果需要解析两个目录下的HTML文件,可在同一目录下创建两个文件夹:

//静态文件,声明模板文件所在的目录,系统自动解析 r.LoadHTMLGlob("static/html/*") r.LoadHTMLGlob("static/html2/*")

[GIN-debug] Loaded HTML Templates (4):
- form.html
- login.html
- upload.html
-

[GIN-debug] Loaded HTML Templates (2):
- uploadMore.html
-

此时将会正常解析两个目录下的HTML模板。

还可以使用:

//静态文件,声明模板文件所在的目录,系统自动解析 r.LoadHTMLGlob("static/**/*") -[GIN-debug] Loaded HTML Templates (5): - form.html - login.html - upload.html - uploadMore.html

static目录下的子目录内的所有模板文件都将被解析。

注意:static目录下的模板文件将不会被解析。

重定向 c.Redirect(http.StatusPermanentRedirect,"http://localhost:8080/updateBook")

状态码可选:

http.StatusPermanentRedirect //永久性重定向

http.StatusTemporaryRedirect //临时性重定向

第二个参数为重定向的地址。

异步处理 // Async 异步处理,保存上传文件,开启相应数量的 goroutine func Async(c *gin.Context) { form, err := c.MultipartForm() if err != nil { c.String(http.StatusBadRequest,fmt.Sprintf("get err %s",err.Error())) } //根据key:‘files’,获取表单中的文件切片 files := form.File["files"] fileSum := len(files) fileName := make([]string,fileSum) //控制上传文件同步问题处理 waitG := sync.WaitGroup{} waitG.Add(fileSum) for index, file := range files { fileName[index] = file.Filename //异步处理时,上下文应该复制一个只读副本,不直接使用原始上下文 cc := c.Copy() go func(c *gin.Context,fileName string,fileUpload *multipart.FileHeader) { defer waitG.Done() fmt.Println("正在保存",fileName) cc.SaveUploadedFile(fileUpload,fileName) }(cc,fileName[index],file) } waitG.Wait() c.String(http.StatusOK,"%s",strings.Join(fileName,",\n")) }

初始写法(错误):

go func() { defer waitG.Done() fmt.Println("正在保存",fileName[index]) cc.SaveUploadedFile(file,fileName[index]) }() } 错误原因总结:

未进行传参,导致只有最后一个文件被上传,通过debug发现,虽然已经做同步处理(使用WaitGroup),但是goroutine内因为延迟求值的原因,导致每次都只是保存最后一个文件。传入参数fileName、fileUpload后,会立即复制参数,不会出现延迟求值的情况,使得保存文件按顺序进行保存。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpswsp.html