5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer
如果不仔细看或者对go语法不够熟悉的话,这里很容易产生一个误解,
注意,这里是新声明了一个结构体,这个结构体相当于“继承”了gin.ResponseWriter的所有属性和方法,并且额外声明了一个body属性
可以对比看一下两者的区别
搞懂了两者的区别之后就好理解了。
这一步就是把我们 c中传递过来的c.Writer(包括其中携带的数据、状态)赋值给我们的w变量。
说白了 还是为了完成我们定义时想做的事情:给我们的c.Writer加一个body的额外属性。
然后代码转到响应处理这部分
我们可以看到,这里使用的就是我们新增的body属性的值。
那么到了这里,我们的值是哪里来的,什么时候被赋值的呢?
这时候我们来分析一下c原始的Writer,也就是它
跟踪代码我们会发现这是一个ResponseWriter类型的数据,
我们再看看ResponseWriter的结构体会发现里边有一个Write的方法
可以发现是在一次请求时某一时刻系统调用了这里的Write方法写入了这部分的应答数据。那么我们想获得这些数据怎么办呢?定义这个方法!又回到了我们自己写的代码中
由于这时候c.Writer是我们定义的resonseBodyWriter。 所以在执行c.Writer.Write()的时候会调用我们自己定义的Write方法,这时候把值通过bytes.Buffer.Write()【r.body是bytes.buffer类型】方法赋值给body即可。然后再调用r.ResponseWriter.Write方法【我们定义的结构体中的ResponseWriter这个结构体的Write方法】,让程序继续执行即可。
注:由于go帮我们做了优化,所以当我们自己定义的c.Writer【即结构体responseBodyWriter】调用原本c.Writer【即结构体ResponseWriter】的其他方法并且没有找的时,会自动去寻找ResponseWriter的相关方法,所以不用担心其他我们未定义的方法因找不到而影响程序正常运行的问题。
楼主写的很好,我后面的分析也跟楼主是一样的,感谢分享!!!
学习了,感谢楼主
go的简炼,荡然无存。有必要搞这么复杂吗?
参见这篇文章:eli.thegreenplace.net/2020/embeddi...