Go调用MailHog /api/v1/events流式接口无输出问题咨询
问题原因
你的代码无法拿到数据的核心原因是/api/v1/events是长连接流式推送接口,和之前调的一次性返回全量列表的/api/v1/messages逻辑完全不同:
- 你使用的
ioutil.ReadAll会持续阻塞等待响应结束(也就是读到连接关闭的EOF标记)才会返回,而这个接口只要MailHog服务正常运行就不会主动断开连接,所以程序会一直卡在读取响应的步骤,根本走不到后续的JSON解析、打印逻辑。 - curl能正常收到输出是因为curl拿到服务端推送的任意一段数据就会立即打印,不会等待整个响应传输完成,和接口的流式特性匹配。
你确实需要通过循环持续监听这个端点,才能实时拿到新邮件到达的推送。
正确实现方案
不要一次性读取整个响应体,要基于响应体创建流读取器,逐段读取服务端推送的事件内容,每拿到一条完整事件就做解析处理,参考实现如下:
package main import ( "bufio" "encoding/json" "fmt" "net/http" ) // MailEvent 对应MailHog推送的事件结构,可根据实际返回字段调整 type MailEvent struct { EventType string `json:"event"` Message struct { ID string `json:"ID"` From struct { Mailbox string `json:"Mailbox"` Domain string `json:"Domain"` } `json:"From"` To []struct { Mailbox string `json:"Mailbox"` Domain string `json:"Domain"` } `json:"To"` Content struct { Body string `json:"Body"` } `json:"Content"` } `json:"message"` } func main() { resp, err := http.Get("http://localhost:8084/api/v1/events") if err != nil { panic(fmt.Sprintf("连接事件接口失败: %v", err)) } defer resp.Body.Close() scanner := bufio.NewScanner(resp.Body) fmt.Println("开始监听新邮件...") // 循环持续读取流内容 for scanner.Scan() { line := scanner.Bytes() // 跳过事件之间的空分隔行 if len(line) == 0 { continue } var event MailEvent if err := json.Unmarshal(line, &event); err != nil { fmt.Printf("解析事件失败,原始内容: %s,错误: %v\n", string(line), err) continue } // 只处理新邮件到达事件 if event.EventType == "message" { fmt.Printf("收到新邮件,发件人: %s@%s\n", event.Message.From.Mailbox, event.Message.From.Domain) // 在此处调用你的自定义处理函数,传入提取到的邮件信息即可 // yourProcessFunc(event.Message) } } if err := scanner.Err(); err != nil { panic(fmt.Sprintf("监听连接异常断开: %v", err)) } }
使用注意事项
/api/v1/events返回的是逐行分隔的独立JSON事件,不是单个完整JSON结构,所以不能等全量内容读完再反序列化- 正式使用建议增加异常断开自动重连逻辑:当扫描循环因为连接错误退出时,等待2-3秒重新发起连接,避免MailHog重启后监听永久失效
- 如果不需要接收所有类型的事件,可以在请求时携带对应参数过滤,减少无效数据的传输处理
内容的提问来源于stack exchange,提问作者ofashow
相关产品推荐
相关产品推荐

