为什么Go httptrace.GotConn中net.Conn无法断言为自定义HasId接口
问题原因
这个问题是Go标准库net/http的内部封装逻辑导致的,核心原因有两点:
http.Transport会对DialContext返回的连接做二次封装
你在自定义DialContext里返回的TrackedConn实例,并不会直接传递到httptrace.ClientTrace的回调中。http.Transport拿到你返回的连接后,会把它包裹进一个未导出的*http.conn内部结构体,这个结构体才是GotConn回调里info.Conn的实际类型。*http.conn仅实现了标准net.Conn接口,没有实现你自定义的HasId接口,所以直接对info.Conn做接口断言必然失败。RemoteAddr()的返回值没有被修改
内部的*http.conn结构体实现net.Conn接口时,所有方法都会直接委托调用你原始传入的TrackedConn的对应方法,所以info.Conn.RemoteAddr()返回的就是你在TrackedConn中自己实现的RemoteAddr()方法返回的值。如果你这个返回值本身实现了HasId接口,断言自然可以成功。
可选解决思路
如果需要在GotConn中拿到自定义连接标识,可以选择两种方案:
- 继续沿用当前
RemoteAddr承载标识的逻辑,直接从RemoteAddr()的返回值中提取标识 - 不依赖接口断言,通过全局连接映射、Context透传等方式关联连接标识
内容的提问来源于stack exchange,提问作者Yang Wei
相关产品推荐
相关产品推荐

