以标准库net/http为例,DefaultClient定义为:
net/http
var DefaultClient = &Client{}
然而,DefaultServeMux被定义为:
var DefaultServeMux = &defaultServeMux var defaultServeMux ServeMux
为一个对象定义两个变量的意义是什么?它比简单的var DefaultServeMux = &ServeMux{}有什么好处?
var DefaultServeMux = &ServeMux{}
bz4sfanl1#
DefaultServeMux部分是布拉德菲茨帕特里克做的优化,我将从comments on the CL中复制并重新格式化他和Matthew Dempsky之间的对话:
DefaultServeMux
马修·登普斯基:
为了确保我理解,问题是做
var x = newFoo()
即使x未使用,也需要调用newFoo()[***]布拉德·菲茨帕特里克:**是的,这会产生:
var x *T func init() { x = newFoo() }
而且链接器似乎从来没有删除过init块,即使它们只分配给那些本来只会被读取的东西。
而
var x = &y var y foo
跳过显式的初始化代码。所以如果x没有被使用,它可以是死代码,沿着所有类型foo的相关代码一起被删除?[***]布拉德·菲茨帕特里克:**是的我已经检查了从最新的源代码(commit 4f4a9c7fff)编译的go二进制文件的大小,我发现那个提交的变化有很大帮助,但是var DefaultServeMux = &ServeMux{}稍微好一点。见下表:| 执行|go二进制文件的大小|| --------------|--------------|| var DefaultServeMux = NewServeMux()|15870476|| var DefaultServeMux =&defaultServeMux;var defaultServeMux ServeMux|15864704(-5772)|| var DefaultServeMux = &ServeMux{}|15864696(-5780)|
更新:
在创建提交时,我试图找出var DefaultServeMux = &defaultServeMux; var defaultServeMux ServeMux和var DefaultServeMux = &ServeMux{}之间的区别(回到go1.7).但是我在我的机器上编译go1.12失败了,所以我放弃了.我找到的是从go1.13到现在(devel go1.21-4f4a9c7fff),这两种实现在对go二进制文件大小的影响方面几乎相同。下面是结果(我的环境是go1.20.3 linux/amd64,我用./make.bash编译了二进制文件):| git标签|var DefaultServeMux = &defaultServeMuxvar defaultServeMux ServeMux|var DefaultServeMux = &ServeMux{}|三角洲|| --------------|--------------|--------------|--------------|| go1.13 |15083862|15083862|0|| go1.14 |15323624|15323624|0|| go1.15 |14272775|14272775|0|| go1.16 |14068974|14068982|+8|| go1.17 |14022237|14022237|0|| go1.18 |14545517|14545517|0|| go1.19 |15302909|15302909|0|| go1.20 |15579106|15579106|0|| 4f4a9c7fff|15864704|小行星15864696|-8|
var DefaultServeMux = &defaultServeMux; var defaultServeMux ServeMux
go1.20.3 linux/amd64
./make.bash
1条答案
按热度按时间bz4sfanl1#
DefaultServeMux
部分是布拉德菲茨帕特里克做的优化,我将从comments on the CL中复制并重新格式化他和Matthew Dempsky之间的对话:马修·登普斯基:
为了确保我理解,问题是做
即使x未使用,也需要调用newFoo()
[***]布拉德·菲茨帕特里克:**
是的,这会产生:
而且链接器似乎从来没有删除过init块,即使它们只分配给那些本来只会被读取的东西。
马修·登普斯基:
而
跳过显式的初始化代码。所以如果x没有被使用,它可以是死代码,沿着所有类型foo的相关代码一起被删除?
[***]布拉德·菲茨帕特里克:**
是的
我已经检查了从最新的源代码(commit 4f4a9c7fff)编译的go二进制文件的大小,我发现那个提交的变化有很大帮助,但是
var DefaultServeMux = &ServeMux{}
稍微好一点。见下表:| 执行|go二进制文件的大小|
| --------------|--------------|
| var DefaultServeMux = NewServeMux()|15870476|
| var DefaultServeMux =&defaultServeMux;var defaultServeMux ServeMux|15864704(-5772)|
| var DefaultServeMux = &ServeMux{}|15864696(-5780)|
更新:
在创建提交时,我试图找出
var DefaultServeMux = &defaultServeMux; var defaultServeMux ServeMux
和var DefaultServeMux = &ServeMux{}
之间的区别(回到go1.7).但是我在我的机器上编译go1.12失败了,所以我放弃了.我找到的是从go1.13到现在(devel go1.21-4f4a9c7fff),这两种实现在对go二进制文件大小的影响方面几乎相同。下面是结果(我的环境是go1.20.3 linux/amd64
,我用./make.bash
编译了二进制文件):| git标签|var DefaultServeMux = &defaultServeMuxvar defaultServeMux ServeMux|var DefaultServeMux = &ServeMux{}|三角洲|
| --------------|--------------|--------------|--------------|
| go1.13 |15083862|15083862|0|
| go1.14 |15323624|15323624|0|
| go1.15 |14272775|14272775|0|
| go1.16 |14068974|14068982|+8|
| go1.17 |14022237|14022237|0|
| go1.18 |14545517|14545517|0|
| go1.19 |15302909|15302909|0|
| go1.20 |15579106|15579106|0|
| 4f4a9c7fff|15864704|小行星15864696|-8|