GoFrame第三天

GoFrame day3

前言

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

请求输入

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

image-20220606143718140

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-20220606144941189

复杂参数

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

参数 结果
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()
}

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

重定向

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

  • 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

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

最后

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

猜你喜欢

转载自blog.csdn.net/shelgi/article/details/125155377