前言

GoFrame是国人开发的一款全面性的基础开发框架,至于其多么优秀,就不用我来说了。看官方文档一眼便知。

官网

参数

话不多说,直接上干货

param

param参数是拼接在路由上的参数,由?开始标记,用k=v的方式获取,以&符分割。

通过Get方法获取

package main

import (
	"fmt"
	"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) {
		fmt.Println(r.Get("q"))
		r.Response.Writef(
			"hello,world",
		)
	})
	s.SetPort(8199)
	s.Run()
}

访问路由http://127.0.0.1:8199/?q=salmon

path

path路径参数,也叫动态路由,这个也是通过Get方式来进行获取,不过key需要在路由上定义,有以下几种方法

  1. {}
  2. :
  3. *
package main

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

func main() {
	s := g.Server()
	s.BindHandler("/{class}-{course}/:name/*act/", func(r *ghttp.Request) {
		r.Response.Writef(
			"%v %v %v %v",
			r.Get("class"),
			r.Get("course"),
			r.Get("name"),
			r.Get("act"),
		)
	})
	s.SetPort(8199)
	s.Run()
}

PostForm

表单参数,这也是经常见到的参数,context-type为 multipart/form-data,使用PostFormValue来接收。

package main

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

func main() {
	s := g.Server()
	s.BindHandler("POST:/", func(r *ghttp.Request) {
		r.PostFormValue("q")
		r.Response.Writef(
			"hello, world",
		)
	})
	s.SetPort(8199)
	s.Run()
}

简易的说下,BindHandler是最为基础的handler,不指定请求方法的前提下是get,如果需要发送其他方法需要更改。

json

请求体的json应该是最常用的参数没有之一了,在goframe中,同样的,也是使用Get方法接收。没想到吧,我也没想到。

而且,如果路由中有动态的参数或者是param参数,用Get获取的话,优先级最高的是请求体。

func main() {
	s := g.Server()
	s.BindHandler("POST:/:rrr", func(r *ghttp.Request) {
		fmt.Println(r.Get("rrr"))
		r.Response.Writef(
			"hello, world",
		)
	})
	s.SetPort(8199)
	s.Run()
}

在这里,我定义了path参数,还有param参数和请求体参数,从最终的结果来看,请求体的参数是优先级最高的。

xml

xml同理,也是使用get来获取,只是现在用xml数据格式的很少,除了微信生态之外,几乎不太常见。

结构体映射

在学习gin等常规web框架中,对于结构体映射一定不陌生,而在goframe同样也有该方法。Parse

type Req struct {
	Www  string `json:"www"`
	Qqqq string `json:"qqqq"`
	Rrr  string `json:"rrr"`
}

func main() {
	s := g.Server()
	s.BindHandler("POST:/:rrr", func(r *ghttp.Request) {
		var req *Req
		err := r.Parse(&req)
		if err != nil {
			fmt.Println("err: ", err)
		}
		fmt.Println(req)
		r.Response.Writef(
			"hello, world",
		)
	})
	s.SetPort(8199)
	s.Run()
}

发送json映射

{
    "www":"sdfad",
    "qqqq":"我是q",
    "rrr":"request body"
}

这是他的默认映射规则,我在结构体标签中加上json纯粹是习惯,这不是必要的。

小结:在其官方文档上,各种说明写的还是比较详细的,比如其绑定默认值,亦或者添加注释等,这里就不搬砖了, 如果接触过其他的web框架,相信对这个goframe看到这里就已经能够自己进行开发了。

ps: 补充一则规则,在翻看源码的时候,发现了他优先级的排序

router < query < body < form < custom

看来还有一个custom自定义参数是优先级最高的

custom

https://goframe.org/pages/viewpage.action?pageId=3670095

fmt.Println(r.Get("rrr"))
r.SetParam("rrr", "salmon啊")
fmt.Println(r.Get("rrr"))

通过SetParam可以覆盖掉原本客户输入的参数,这个可以用作于加密或者去除空格什么的。

数据校验

goframe内置了数据校验规则,地址在这

这里就不搬砖了,与一般校验规则无二,值得注意的是,可以根据标签中的|#来分别增加校验规则以及返回注释

type Req struct {
	Www  string
	Qqqq string
	Bsa  string `p:"rrr" v:"required|length:6,30#必填项|长度不符合规范"`
}

func main() {
	s := g.Server()
	s.BindHandler("POST:/", func(r *ghttp.Request) {
		var req *Req
		err := r.Parse(&req)
		if err != nil {
			_ = r.Response.WriteJsonExit(map[string]string{
				"code": "400",
				"msg":  err.Error(),
			})
		}
		r.Response.Writef(
			"hello, world",
		)
	})
	s.SetPort(8199)
	s.Run()
}

有一丢丢的小问题啊,注释返回时第一条怎么也达不成效果,在研究中,后续再补充

响应

直接通过response下的方法返回对应响应,这个也无需多言

缓冲区

https://goframe.org/pages/viewpage.action?pageId=3670103

响应不是一个原子性的,如若你使用了多个Response对象来分别写入,如:

func main() {
	s := g.Server()
	s.BindHandler("/", func(r *ghttp.Request) {
		r.Response.Writeln("hello")
		_ = r.Response.WriteJsonExit(map[string]string{
			"code": "1000",
			"msg":  "hello world",
		})
	})
	s.EnableAdmin()
	s.SetPort(8199)
	s.Run()
}

你会发现,他的响应结果是叠加的状态,这也就是他缓冲区存在的必要性。除非,你调用的是Exit结尾的Write。否则结果总是会叠加的。