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

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


最后


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


目录
相关文章
|
SQL 安全 Go
GoFrame ORM 使用实践分享
今天这篇把我使用GoFrame ORM的过程中认为有价值、可能踩坑、比较好的实践等相关的知识点分享出来。
807 0
|
3月前
|
Linux 编译器 开发工具
Linux下Zlib安装与使用教程 (从入门到精通的Zlib压缩库开发指南)
本文参考:http://iyjla.cn详解Linux下Zlib压缩库的安装与使用:涵盖源码下载、编译安装(configure/make/make install)、头文件与库链接,以及基础C程序调用示例,助开发者快速掌握这一通用开源压缩工具。(239字)
vue3-element-admin的组件el-time-picker设置只能选择上午或下午
vue3-element-admin的组件el-time-picker设置只能选择上午或下午
1087 0
|
存储 云计算
阿里云国际版和阿里云中国站有什么不一样?
最近阿里云国际站的呼声也很高,那么阿里云国际站是什么呢?跟中国站又有什么不同呢?可以搜索了解有什么区别
|
消息中间件
rabbitmq每小时自动重启
rabbitmq每小时自动重启
1030 2
rabbitmq每小时自动重启
|
Web App开发 移动开发 JavaScript
实时监听输入框值变化的完美方案:oninput & onpropertychange
  在 Web 开发中经常会碰到需要动态监听输入框值变化的情况,如果使用 onkeydown、onkeypress、onkeyup 这个几个键盘事件来监测的话,监听不了右键的复制、剪贴和粘贴这些操作,处理组合快捷键也很麻烦。
1589 0
|
NoSQL Redis 数据库
GoFrame gredis 配置管理 | 配置文件、配置方法的对比
goframe框架支持两种方式来管理redis配置和获取redis对象,一种是通过配置文件+单例对象的方式;一种是模块化通过配置管理方法及对象创建方法。
649 0
node 版本与npm版本不相匹配
node 版本与npm版本不相匹配
2048 0
node 版本与npm版本不相匹配
|
开发工具 git
Git恢复之前版本的两种方法reset、revert(图文详解)
Git恢复之前版本的两种方法reset、revert(图文详解)
2154 0
ECharts 饼图指定颜色显示
ECharts 饼图指定颜色显示
2237 0

热门文章

最新文章