5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer

如果不仔细看或者对go语法不够熟悉的话,这里很容易产生一个误解,
5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer
注意,这里是新声明了一个结构体,这个结构体相当于“继承”了gin.ResponseWriter的所有属性和方法,并且额外声明了一个body属性
可以对比看一下两者的区别

5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer

5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer

搞懂了两者的区别之后就好理解了。

5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer
这一步就是把我们 c中传递过来的c.Writer(包括其中携带的数据、状态)赋值给我们的w变量。
说白了 还是为了完成我们定义时想做的事情:给我们的c.Writer加一个body的额外属性。

然后代码转到响应处理这部分

5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer
我们可以看到,这里使用的就是我们新增的body属性的值。

那么到了这里,我们的值是哪里来的,什么时候被赋值的呢?
这时候我们来分析一下c原始的Writer,也就是它
5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer
跟踪代码我们会发现这是一个ResponseWriter类型的数据,

5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer

我们再看看ResponseWriter的结构体会发现里边有一个Write的方法
5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer

可以发现是在一次请求时某一时刻系统调用了这里的Write方法写入了这部分的应答数据。那么我们想获得这些数据怎么办呢?定义这个方法!又回到了我们自己写的代码中
5.4. "HTTP 访问日志" 中为什么要单独建立一个结构体去重新赋值给c.Writer

由于这时候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的相关方法,所以不用担心其他我们未定义的方法因找不到而影响程序正常运行的问题。

讨论数量: 6

楼主写的很好,我后面的分析也跟楼主是一样的,感谢分享!!!

1年前 评论
joker_hu (楼主) 1年前

学习了,感谢楼主

1年前 评论
joker_hu (楼主) 1年前

go的简炼,荡然无存。有必要搞这么复杂吗?

8个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!