在软件开发中,错误和挑战是无法避免的一部分。无论是经验丰富的开发者还是初学者,在实现项目的过程中都可能会遇到各种问题和错误。在本篇博客中,我将列举一些我曾经在用Go语言实现项目时遇到的一些错误,以及如何解决这些问题。
1. golang接口与实现以及var _ I = (*T)(nil)的意义
var _ I = (*T)(nil) 这行代码要求后面的结构体必须实现前面的接口,不然会出现编译错误。
今天在看书的时候发现了这么一句话var _ HelloServiceInterface = (*HelloServiceClient)(nil),其中HelloServiceClient是一个结构体,另外一个自然是一个interface。代码的作者称这行代码要求后面的结构体必须实现前面的接口,不然会出现编译错误。
说实话,我第一眼真的没反应过来。直到我看到了这个问题 这一行实际上是变量赋值的变体var VariableName variableType = variableValue,其中的值是(*HelloServiceClient)类型,实际值为nil。
另外有类似的语句:
//T is a struct
var _ I = T{} // Verify that T implements I.
var _ I = (*T)(nil) // Verify that *T implements I.
var _ I = &T{}
这个问题的本质其实是接口的定义:结构体只要实现了接口的定义,它就能被赋予该接口的变量。 对于指针来说就要更复杂一些,详见#180 。概要来说,就是对用指针实现的接口,该指针类型的普通结构体不能使用,具体原因也比较复杂(详见Go程序设计与实现-接口相关章节)
参考:
cloud.tencent.com/developer/a…
2. gob error encoding body: gob: type mr.Task has no exported fields
解决方法:把结构体中字段开头变成大写
举例: 系列化和反系列化的常见的错误
如果是你的结构体的字段是小写开头 gob序列化你的结构体的时候会找不到字段
如果我把
type Person struct{
Age int
Name string
}
改成
type Person struct {
age int
name string
}
编码器 解码错误 gob: type main.Person has no exported fields
参考:
Go语言采坑记录gob序列化坑_gob: wrong type (string) for received field invoke
3. gin框架参数零值json绑定的问题
项目中使用gin框架,post请求之类的用json传参,过程中遇到的一个问题是:如果给字段binding一个required必填,那么这个字段就没办法传入对应数据类型的零值。同时对应的另一个问题是,如果不是required的字段,传参校验无法确定传入参数是数据类型的零值还是根本没传这个字段。
解决方法:go gin框架 binding:"required"无法接收零值,只要把类型定义为指针类型即可接受零值
参考例子:
(1)不能接受零值的例子
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"log"
)
// Student
// 假设前端需要传入参数name,age,sex
// name表示学生的姓名(必填)
// age表示学生的年龄(必填)
// sex表示学生的性别,0是女,1是男(必填)
type Student struct {
Name string `json:"name" binding:"required"`
Age int `json:"age" binding:"required"`
Sex int `json:"sex" binding:"required"`
}
func main() {
engine := gin.Default() //创建一个默认的引擎
//请求 http://127.0.0.1:8090/student/add
engine.POST("/student/add", func(context *gin.Context) {
student := Student{}
err := context.ShouldBind(&student)
if err != nil {
log.Printf("参数错误:%v", err)
context.JSON(200, gin.H{"success": false, "msg": err.Error()})
return
}
context.JSON(200, gin.H{"success": true, "msg": ""})
return
})
err := engine.Run("0.0.0.0:8090") //启动引擎,端口是8090
if err != nil {
panic(fmt.Sprintf("启动引擎失败,失败信息:%s", err.Error()))
}
}
前端传入参数,性别为0,则报error
Key: 'Student.Sex' Error:Field validation for 'Sex' failed on the 'required' tag
(2)可以接受零值的例子
只需要把
Sex int json:"sex" binding:"required"
变成
Sex *int json:"sex" binding:"required"
即可
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"log"
)
// Student
// 假设前端需要传入参数name,age,sex
// name表示学生的姓名(必填)
// age表示学生的年龄(必填)
// sex表示学生的性别,0是女,1是男(必填)
type Student struct {
Name string `json:"name" binding:"required"`
Age int `json:"age" binding:"required"`
Sex *int `json:"sex" binding:"required"`
}
func main() {
engine := gin.Default() //创建一个默认的引擎
//请求 http://127.0.0.1:8090/student/add
engine.POST("/student/add", func(context *gin.Context) {
student := Student{}
err := context.ShouldBind(&student)
if err != nil {
log.Printf("参数错误:%v", err)
context.JSON(200, gin.H{"success": false, "msg": err.Error()})
return
}
context.JSON(200, gin.H{"success": true, "msg": ""})
return
})
err := engine.Run("0.0.0.0:8090") //启动引擎,端口是8090
if err != nil {
panic(fmt.Sprintf("启动引擎失败,失败信息:%s", err.Error()))
}
}
参考:
解决go gin框架 bindingrequired`无法接收零值的问题
4. go语言的null值问题
要点
- 从数据库读取可能为null值得值时,可以选择使用
sql.NULL来读取;或者使用IFNULL、COALESCE等命令让数据库查询值返回不为或者NULL - 若需要往数据库中插入null值,则依然可以使用
sql.NULL存储所需的值,然后进行插入NULL值 - 直接使用
sql.NULL类型容易出现valid遗漏设置等问题,普通int、string与其转换时,请写几个简单的get、set函数
参考:
Go语言:解决数据库中null值的问题_sql.nullint64_绯浅yousa的博客-CSDN博客
总结
在使用Go语言开发项目时,常常会遇到各种各样的错误。这些错误可能会在开发过程中耗费时间和精力,但它们也是学习和成长的机会。通过了解常见错误的原因,以及采取相应的预防和解决措施,开发者可以更加从容地面对问题,提高代码质量和项目的稳定性。在实践中,积累经验并不断学习是不断成长的关键。
CSDN吃相真难看,我引用的参考是我以前找到的能够解决问题的博客,但目前好几篇都变成了VIP文章,开通会员才能访问