GoFrame第三天

简介: GoFrame第三天

GoFrame day3


前言


上一次总结了路由相关的内容,今天就接着继续总结.当我们访问某个api的时候往往需要根据路由请求带有的参数来实现内部的操作,所以来看看怎么获得参数以及进行数据返回.


请求输入


我们在路由注册的时候都依靠ghttp.Request对象来实现页面操作处理,我们也可以通过这个对象的方法获得请求参数.


image.png


ghttp_request_param.go中可以看到相关的方法,并且看源码中所有的值都是...interface{}也就是最近推出的any,使得每个解析出来的参数值都是泛型变量.最简单的获取路由参数例子如下


package main
import (
  "github.com/gogf/gf/v2/frame/g"
  "github.com/gogf/gf/v2/net/ghttp"
)
func main() {
  s := g.Server()
  s.BindHandler("/", func(r *ghttp.Request) {
    r.Response.Writeln(r.Get("xxx").String())
  })
  s.SetPort(8080)
  s.Run()
}
复制代码


image.png


复杂参数


当我们请求的参数较为复杂时,对应不同的情况会有不同的解析结果,下面就是各种情况的总结


参数 结果
k=m&k=n map[k:n]
k1=m&k2=n map[k1:m k2:n]
k[]=m&k[]=n map[k:[m n]]
k[a][]=m&k[a][]=n map[k:map[a:[m n]]]
k[a]=m&k[b]=n map[k:map[a:m b:n]]
k[a][a]=m&k[a][b]=n map[k:map[a:map[a:m b:n]]]
k=m&k[a]=n error


对象处理


一般将输入输出定义为结构体对象,并且提交的参数可以很好的映射到预先定义的结构体属性上.默认的转换规则如下

  1. struct中需要匹配的属性必须为**公开属性**(首字母大写)。
  2. 参数名称会自动按照 不区分大小写忽略-/_/空格符号 的形式与struct属性进行匹配。
  3. 如果匹配成功,那么将键值赋值给属性,如果无法匹配,那么忽略该键值。

当然我们为了简单也可以自定义参数的映射规则,使用aaa typename p:"xxx"可以将xxx映射到结构体aaa属性上


package main
import (
  "github.com/gogf/gf/v2/frame/g"
  "github.com/gogf/gf/v2/net/ghttp"
)
type RegisterReq struct {
  Name  string
  Pass  string `p:"password1"`
  Pass2 string `p:"password2"`
}
type RegisterRes struct {
  Code  int         `json:"code"`
  Error string      `json:"error"`
  Data  interface{} `json:"data"`
}
func main() {
  s := g.Server()
  s.BindHandler("/register", func(r *ghttp.Request) {
    var req *RegisterReq
    if err := r.Parse(&req); err != nil {
      r.Response.WriteJsonExit(RegisterRes{
        Code:  1,
        Error: err.Error(),
      })
    }
    // ...
    r.Response.WriteJsonExit(RegisterRes{
      Data: req,
    })
  })
  s.SetPort(8080)
  s.Run()
}
复制代码


image.png


请求校验


GoFrame有强大的请求校验功能,可以给我们定义的结构体绑定v标签来实现参数校验.但是貌似这里有个bug问题,如果我们利用自定义的swagger加上v标签校验的话就会导致验证错误,无法使用try it out.当然也有其他人遇到了这个问题,具体可以看看这个issue,目前这个bug已经在2.1.0-rc4中被修复,希望下一个版本的GoFrame能更加完美.


默认值


当我们需要设置默认值的时候,可以在结构体的属性中添加d标签


数据返回


当我们处理完请求参数,可以利用请求参数实现一些逻辑,但是最终还是要返回结果给页面,这个时候就需要利用一些数据返回接口了.


缓冲控制


Response输出采用了缓冲控制,输出的内容预先写入到一块缓冲区,等待服务方法执行完毕后才真正地输出到客户端。该特性在提高执行效率同时为输出内容的控制提供了更高的灵活性。


当服务出现异常时,通常需要将错误信息对用户隐藏,转而设置为统一的错误信息,这个时候可以利用中间件的后置处理,将异常信息清除并转为提示信息输出


package main
import (
  "net/http"
  "github.com/gogf/gf/v2/frame/g"
  "github.com/gogf/gf/v2/net/ghttp"
)
func MiddlewareErrorHandler(r *ghttp.Request) {
  r.Middleware.Next()
  if r.Response.Status >= http.StatusInternalServerError {
    r.Response.ClearBuffer()
    r.Response.Writeln("服务器居然开小差了,请稍后再试吧!")
  }
}
func main() {
  s := g.Server()
  s.Group("/api.v2", func(group *ghttp.RouterGroup) {
    group.Middleware(MiddlewareErrorHandler)
    group.ALL("/user/list", func(r *ghttp.Request) {
      panic("db error: sql is xxxxxxx")
    })
  })
  s.SetPort(8080)
  s.Run()
}


image.png



当然也可以试试清除缓冲区和不清除缓冲区的区别


重定向


更多时候需要实现一些页面跳转功能,这个时候就需要用到重定向.

  • RedirectTo()可以将页面重定向到另外一个路由
  • RedirectBack()返回上一个页面

下面就简单实现一个页面跳转的demo


package main
import (
  "github.com/gogf/gf/v2/frame/g"
  "github.com/gogf/gf/v2/net/ghttp"
)
func main() {
  s := g.Server()
  s.BindHandler("/", func(r *ghttp.Request) {
    r.Response.RedirectTo("/login")
  })
  s.BindHandler("/login", func(r *ghttp.Request) {
    r.Response.Writeln(`<a href="/home">Redirect to home</a>`)
  })
  s.BindHandler("/home", func(r *ghttp.Request) {
    r.Response.Writeln(`<a href="/login">Back to login</a>`)
    //r.Response.RedirectBack()
  })
  s.SetPort(8080)
  s.Run()
}
复制代码


可以试试加与不加RedirectBack()的效果


文件下载


可以使用ServeFileServeFileDownload分别实现文件展示,文件格式识别与下载


package main
import (
  "github.com/gogf/gf/v2/frame/g"
  "github.com/gogf/gf/v2/net/ghttp"
)
func main() {
  s := g.Server()
  s.BindHandler("/show", func(r *ghttp.Request) {
    r.Response.ServeFile("test.txt")
  })
  s.BindHandler("/download", func(r *ghttp.Request) {
    r.Response.ServeFileDownload("test.txt")
  })
  s.SetPort(8080)
  s.Run()
}


image.png

下载页面会直接弹出文件下载框,大家可以自己访问看效果


最后


今天这里总结了大部分的常用处理,但是留了一个小坑—文件上传部分的内容留到下次单独讲.


目录
相关文章
|
25天前
|
移动开发 网络协议 数据格式
【VOFA+速成】半小时入门VOFA+简明教程之基础认识(一)
【VOFA+速成】半小时入门VOFA+简明教程(一)
|
XML 监控 数据可视化
马老师力荐:腾讯SpringBoot高阶笔记,限时开源48小时
众所周知,SpringBoot最大的一个优势就是可以进行自动化配置,简化配置,不需要编写太多的xml配置文件;基于Spring构建,使开发者快速入门,门槛很低;SpringBoot可以创建独立运行的应用而不需要依赖于容器;内置tomcat服务器,不需要打包成war包,可以直接放到tomcat中运行;提供maven极简配置,以及可视化的相关监控功能,比如性能监控,应用的健康程度等;为微服务SpringCloud奠定了基础,使得微服务的构建变得简单;Spring可以整合很多各式各样的框架,并能很好的集成。
|
前端开发 JavaScript 程序员
重学JavaWeb第三天(十一)
重学JavaWeb第三天(十一)
81 0
|
JSON 程序员 开发工具
开发同学实用Alfred Workflow - Sanctuary(不定期更新)
说明程序员实用工具箱,包含时间戳与格式化时间相互转换、Json和kv格式数据相互转换、url encode和decode等功能。开箱即用,无额外配置&依赖需购买Powerpackd,请支持正版要求Alfred5,低版本没测试过,若低版本不可用可自行创建把代码copy过去为什么没用git保存项目?用chatgpt生成的,代码没太多研究维护价值如有其他需求,欢迎交流,一起完善功能时间戳与格式化
316 0
|
前端开发 JavaScript NoSQL
SpringBoot日记本系统全程直播05:把日记新增功能搞出来撒~
SpringBoot日记本系统全程直播05:把日记新增功能搞出来撒~
|
前端开发 网络协议 jenkins
三分钟,我让搞后端的学弟爱上了Eolink
突然某一天,一个特别能卷的学弟向我请教接口工具……
三分钟,我让搞后端的学弟爱上了Eolink
|
存储 NoSQL Java
GoFrame避坑指南和实践干货(2)
用GoFrame已经开发了一段时间,今天为大家分享避坑指南和实践干货。这些坑并不是框架设计者的问题,更多的是我作为初学者的各种摸石头过河
212 0
GoFrame避坑指南和实践干货(2)
GoFrame第四天
GoFrame第四天
225 0
GoFrame第四天
|
缓存 中间件 API
GoFrame第二天
GoFrame第二天
304 0
GoFrame第二天
|
安全 NoSQL 数据库连接
GoFrame第五天
GoFrame第五天
240 0
GoFrame第五天