用gin写的后端接口,并发高的时候请求延迟过高,因此考虑通过goroutine并发请求,降低请求延迟。
在使用 gin 和 goroutine 返回数据时 Context.JSON()
在 goroutine 内是无法正确调用的,会报空指针错误。
需要将该函数放在 goroutine 外,用 channel 传值作为参数。
type Response struct {
Code int
Obj gin.H
}
func ErrorResponse(err error) Response {
log.Printf("查询的时候出错了 %s \n", err)
return Response{
Code: http.StatusInternalServerError,
Obj: gin.H{"error": err.Error()},
}
}
func DataResponse(obj any) Response {
return Response{
Code: http.StatusOK,
Obj: gin.H{"data": obj},
}
}
func findApps(c *gin.Context) {
// 创建 channel
ch := make(chan Response)
//
go func(c *gin.Context) {
data, err := FindStudentByName(c.Query("name"))
// 将值发送到 channel
if err != nil {
ch <- ErrorResponse(err)
}
ch <- DataResponse(data)
}(c.Copy())
// 接收 channel 中的值
response := <-ch
c.JSON(response.Code, response.Obj)
}
参考
在Go语言中,channel和goroutine是紧密相关的概念。
goroutine是一种轻量级的线程,它可以在一个程序中并发执行多个任务,可以看作是Go语言的并发单位。
channel是goroutine之间进行通信的管道,通过channel,一个goroutine可以向另一个goroutine发送数据或接收数据,实现了goroutine之间的同步和通信。
goroutine和channel之间的关系可以类比为"工人"和"传送带"的关系。工人就是goroutine,传送带就是channel,工人们可以在自己的工作区域内工作,但是需要和其他工人进行协作,这时就需要把产品通过传送带传递给其他工人。同样地,goroutine也需要通过channel来进行通信和协作。
在Go语言中,channel和goroutine的配合使用,可以极大地提高程序的并发能力和效率。