golang/gin常见用法和问题
结构体数组与接口数组转换
如果想把[]struct转为[]interface,我们发现直接赋值会报错。
理论上interface可以转换任何数据,为什么结构体数组不可以呢?这是因为interface的设计导致的,如果能理解interface的底层实现,就能很清楚知道如何转换了。
如图所示,与C++的虚函数类似,interface保存了两部分内容,一部分是数据类型,另一部分是数据,所以可以被转化为任何数据。[]struct是被当作一个整体看待的,[]struct与struct,或者与int都没区别,表示一种数据类型。[]struct可以转换为interface,但是[]interface表示有一组interface,一个[]struct,当然不可能转化为多个interface,也就不能转化为[]interface。
实际上我们的意思是把[]struct中的每个元素作为独立个体,再对应[]iterface中的每个interface。既然理解到这一层,就可以很好的实现转换了:
// 根据[]struct x的元素个数,创建对应的[]interface y
y := make([]interface{}, len(x))
// 遍历[]struct x中的每个元素,转换为[]interface y中的每个元素
for i, v := range x {
y[i] = v
}
https://go.dev/doc/faq#convert_slice_of_interface
https://research.swtch.com/interfaces
https://stackoverflow.com/questions/44319906/why-golang-struct-array-cannot-be-assigned-to-an-interface-array
post发送的数据接收不到
如图所示,postman发送的方式有很多种,如果gin注册了post路由,那么数据不可以使用params发送,这个不是post的数据。
应该在body中增加post数据,并且如果代码中定义接收数据的结构体是json类型,如下:
type TEST struct {
VALUE string `json:"value" binding:"required"`
}
那么postman发送时,body界面,选择raw(源数据),后面还要选择JSON,默认是TEXT。如果是TEXT,由于content-type不匹配,会收不到数据。
如果boday类型选择form-data或者x-www-form-urlencoded,那么接收的结构体也要设定为对应的类型,增加form类型指定。
type CreateRequest struct {
Username string `json:"username" form:"username"`
Phone string `json:"phone" form:"phone"`
Password string `json:"password" form:"password"`
}
https://stackoverflow.com/questions/53705933/gin-framework-can-not-get-the-data-from-postman
gin通过bind获取数值为0的设置为required的整数报错的问题
如果设置了一个整数为required
type Test struct {
Num int `json:"num" binding:"required"`
}
但是前端post的数据是0 "num": 0
,那么通过bind获取数据,会报错
var t = Test{}
err := c.Bind(&t)
具体原因就是说,required检测认为默认值,也就是数值变量为0,是错误的(不亏说golang是邪教,一群开发者很固执,这个问题死活不改)。然后很多讨论说提供了一个exists参数代替required,但是我们用的是binding,而不是validator,虽然我看讨论说是可以,但是我试了,会报错 Undefined validation function 'exists' 。
有人说上面的错误是因为用的validator版本太老是v8,应该用v9,我看我的go.mod中用的都是v10了,所以不知道为什么。
最后解决方案是把可能是0的整数设置为指针类型,go会根据类型自动挡填充数据,前端post数据不变,只不过访问的时候注意是指针
type Test struct {
Num *int `json:"num" binding:"required"`
}
https://github.com/gin-gonic/gin/issues/491
https://github.com/go-playground/validator/issues/142
https://github.com/gin-gonic/gin/issues/737
https://github.com/gin-gonic/gin/issues/690
https://pkg.go.dev/gopkg.in/go-playground/validator.v8#section-readme
https://github.com/gin-gonic/gin/issues/2160
https://github.com/go-playground/validator/issues/692
https://github.com/go-playground/validator/issues/692