Goroutine未向Channel写入数据问题求助
问题分析与修复
你的代码存在几个关键问题,导致通道无法正确接收PDF数据:
1. 变量遮蔽导致包调用错误
goroutine中的代码pdf, err := pdf.GenerateFromHTML(...)存在变量遮蔽问题:左边声明的pdf局部变量覆盖了同名的pdf包(假设pdf是你导入的PDF生成包),导致实际调用的是未初始化的变量方法而非包函数。这会引发逻辑错误,即使你认为获取到了PDF值,也可能是错误的结果。
2. goroutine内的错误无法传递到主流程
goroutine中使用:=声明的err是局部变量,主函数中的if err != nil检查的是base64.DecodeString的错误,完全无法感知GenerateFromHTML的执行错误。如果GenerateFromHTML实际返回错误,goroutine不会往通道发送数据,主goroutine接收已关闭的通道会得到零值(空切片),最终返回空PDF。
修复后的代码
func (h *Handler) GeneratePdfFromHTML(c echo.Context) (err error) { req := &createPdfFromHTMLRequest{} if err := req.bind(c); err != nil { return c.JSON(http.StatusBadRequest, utils.NewError(err)) } rawDecodedText, err := base64.StdEncoding.DecodeString(req.HTML) if err != nil { return c.JSON(http.StatusInternalServerError, utils.NewError(err)) } // 定义结构体传递数据和错误 type pdfResult struct { data []byte err error } buf := make(chan pdfResult) go func() { defer close(buf) // 重命名变量,避免遮蔽包名 pdfData, err := pdf.GenerateFromHTML(string(rawDecodedText)) // 无论成功失败,都往通道传递结果 buf <- pdfResult{data: pdfData, err: err} }() // 接收goroutine的执行结果 res := <-buf if res.err != nil { return c.JSON(http.StatusInternalServerError, utils.NewError(res.err)) } return c.Blob(http.StatusOK, MIMEApplicationPdf, res.data) }
额外说明
- 通过自定义结构体
pdfResult,可以同时传递PDF数据和错误,确保主流程能感知goroutine内的执行状态。 - 重命名goroutine内的变量为
pdfData,彻底避免包名与变量名冲突的问题。 - 移除了主函数中多余的
if err != nil检查,该检查的是之前DecodeString的错误,已经在前面的分支处理完毕。
内容的提问来源于stack exchange,提问作者Aníbal Deboni Neto
相关产品推荐
相关产品推荐

