<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>《对一段Go语言代码输出结果的简要分析》的评论</title>
	<atom:link href="http://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/feed/" rel="self" type="application/rss+xml" />
	<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/</link>
	<description>一个程序员的心路历程</description>
	<lastBuildDate>Wed, 25 Mar 2026 09:21:20 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
	<item>
		<title>作者：Gavin</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7258</link>
		<dc:creator>Gavin</dc:creator>
		<pubDate>Mon, 20 Aug 2018 03:39:00 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7258</guid>
		<description>这个有意思了，没有解读，完全没有头绪， 我居然还在在思考 return 和 defer的顺序...
惭愧惭愧</description>
		<content:encoded><![CDATA[<p>这个有意思了，没有解读，完全没有头绪， 我居然还在在思考 return 和 defer的顺序&#8230;<br />
惭愧惭愧</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：bigwhite</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7160</link>
		<dc:creator>bigwhite</dc:creator>
		<pubDate>Wed, 28 Mar 2018 03:31:19 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7160</guid>
		<description>嗯，和goroutine调度顺序有关系。</description>
		<content:encoded><![CDATA[<p>嗯，和goroutine调度顺序有关系。</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：yale</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7159</link>
		<dc:creator>yale</dc:creator>
		<pubDate>Wed, 28 Mar 2018 03:24:10 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7159</guid>
		<description>修改一下上面评论
“这样导致最后一个协程启动时拿到的地址是最后一个循环变量的地址”
为
“这样导致这些协程启动时拿到的变量地址都是最后一个循环变量的地址”</description>
		<content:encoded><![CDATA[<p>修改一下上面评论<br />
“这样导致最后一个协程启动时拿到的地址是最后一个循环变量的地址”<br />
为<br />
“这样导致这些协程启动时拿到的变量地址都是最后一个循环变量的地址”</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：yale</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7158</link>
		<dc:creator>yale</dc:creator>
		<pubDate>Wed, 28 Mar 2018 03:19:56 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7158</guid>
		<description>for _, v := range data2 {
        go print(&amp;v)
    }   
感谢作者分析的如此详细，我再加一点我的理解，这块有问题的一个重要原因是不是for执行太快，go 启动协程慢，速度不匹配，这样导致最后一个协程启动时拿到的地址是最后一个循环变量的地址，如果这块加个延迟也可以获取正确结果：

    for _, v := range data2 {
        go print(&amp;v)
        time.Sleep(1 * time.Second)
    }   
  当然了，这种做法不可能用到实际中，只是分析分析</description>
		<content:encoded><![CDATA[<p>for _, v := range data2 {<br />
        go print(&amp;v)<br />
    }<br />
感谢作者分析的如此详细，我再加一点我的理解，这块有问题的一个重要原因是不是for执行太快，go 启动协程慢，速度不匹配，这样导致最后一个协程启动时拿到的地址是最后一个循环变量的地址，如果这块加个延迟也可以获取正确结果：</p>
<p>    for _, v := range data2 {<br />
        go print(&amp;v)<br />
        time.Sleep(1 * time.Second)<br />
    }<br />
  当然了，这种做法不可能用到实际中，只是分析分析</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：开发者头条</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7156</link>
		<dc:creator>开发者头条</dc:creator>
		<pubDate>Mon, 26 Mar 2018 02:26:58 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7156</guid>
		<description>您好，我是开发者头条的运营。您的《对一段 Go 语言代码输出结果的简要分析》已被我们平台用户推荐到首页。感谢您的辛苦创作，为了让更多读者认识您，我们邀请您来开发者头条分享。与创作不同，您仅需复制粘贴文章链接即可完成分享。您可以在各大应用市场搜索 “开发者头条” 找到我们的应用，欢迎了解。期待您的分享。</description>
		<content:encoded><![CDATA[<p>您好，我是开发者头条的运营。您的《对一段 Go 语言代码输出结果的简要分析》已被我们平台用户推荐到首页。感谢您的辛苦创作，为了让更多读者认识您，我们邀请您来开发者头条分享。与创作不同，您仅需复制粘贴文章链接即可完成分享。您可以在各大应用市场搜索 “开发者头条” 找到我们的应用，欢迎了解。期待您的分享。</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：cumirror</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7154</link>
		<dc:creator>cumirror</dc:creator>
		<pubDate>Thu, 22 Mar 2018 02:42:50 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7154</guid>
		<description>golang的语法特性很有趣，多谢细致解答~</description>
		<content:encoded><![CDATA[<p>golang的语法特性很有趣，多谢细致解答~</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：bigwhite</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7153</link>
		<dc:creator>bigwhite</dc:creator>
		<pubDate>Wed, 21 Mar 2018 15:54:44 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7153</guid>
		<description>我再详细说一下吧。

你的例子中的代码：

package main

import &quot;fmt&quot;

func main() { 
    var i int = 1

    defer fmt.Println(&quot;result =&gt;&quot;,func() int { return i * 2 }())
    i++
    //prints: result =&gt; 2 (not ok if you expected 4)
}


当代码执行到defer时，需要对defer后面的function进行参数求值，而后面的function是Println，就需要对Println的参数进行求值，于是执行了那个匿名函数。匿名函数是一个闭包函数，此时i=1，于是求值结果是2，相当于defer fmt.Println(&quot;result =&gt;&quot;,2)


而我改变的这个例子：

package main

import &quot;fmt&quot;

func main() {
    var i int = 1

    defer func() {

        fmt.Println(&quot;result =&gt;&quot;, func() int { return i * 2 }())
    }()
    i++
    //prints: result =&gt; 2 (not ok if you expected 4)
}

同样执行到defer，对defer后面的函数的参数求值，发现没有参数，于是跳过。当main返回前，执行defer，这时func中println参数中的闭包函数求值，此时i=2了，于是输出4.</description>
		<content:encoded><![CDATA[<p>我再详细说一下吧。</p>
<p>你的例子中的代码：</p>
<p>package main</p>
<p>import “fmt”</p>
<p>func main() {<br />
    var i int = 1</p>
<p>    defer fmt.Println(“result =&gt;”,func() int { return i * 2 }())<br />
    i++<br />
    //prints: result =&gt; 2 (not ok if you expected 4)<br />
}</p>
<p>当代码执行到defer时，需要对defer后面的function进行参数求值，而后面的function是Println，就需要对Println的参数进行求值，于是执行了那个匿名函数。匿名函数是一个闭包函数，此时i=1，于是求值结果是2，相当于defer fmt.Println(“result =&gt;”,2)</p>
<p>而我改变的这个例子：</p>
<p>package main</p>
<p>import “fmt”</p>
<p>func main() {<br />
    var i int = 1</p>
<p>    defer func() {</p>
<p>        fmt.Println(“result =&gt;”, func() int { return i * 2 }())<br />
    }()<br />
    i++<br />
    //prints: result =&gt; 2 (not ok if you expected 4)<br />
}</p>
<p>同样执行到defer，对defer后面的函数的参数求值，发现没有参数，于是跳过。当main返回前，执行defer，这时func中println参数中的闭包函数求值，此时i=2了，于是输出4.</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：bigwhite</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7152</link>
		<dc:creator>bigwhite</dc:creator>
		<pubDate>Wed, 21 Mar 2018 15:48:39 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7152</guid>
		<description>defer关键字一定是对后面的函数的参数即时进行参数求值的，你可以对比一下这个：https://play.golang.org/p/Eux7zpSr7O8

我也在最新spec中找了一下：

关于method 本质的描述之一：The type of a method is the type of a function with the receiver as first argument.

关于对receiver自动deference或auto take address，可以参见下面的spec中的描述：

As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.

As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&amp;t).Mp.</description>
		<content:encoded><![CDATA[<p>defer关键字一定是对后面的函数的参数即时进行参数求值的，你可以对比一下这个：https://play.golang.org/p/Eux7zpSr7O8</p>
<p>我也在最新spec中找了一下：</p>
<p>关于method 本质的描述之一：The type of a method is the type of a function with the receiver as first argument.</p>
<p>关于对receiver自动deference或auto take address，可以参见下面的spec中的描述：</p>
<p>As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer: pt.Mv is equivalent to (*pt).Mv.</p>
<p>As with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value: t.Mp is equivalent to (&amp;t).Mp.</p>
]]></content:encoded>
	</item>
	<item>
		<title>作者：cumirror</title>
		<link>https://tonybai.com/2018/03/20/the-analysis-of-output-results-of-a-go-code-snippet/#comment-7150</link>
		<dc:creator>cumirror</dc:creator>
		<pubDate>Wed, 21 Mar 2018 13:51:07 +0000</pubDate>
		<guid isPermaLink="false">http://tonybai.com/?p=2571#comment-7150</guid>
		<description>多谢解惑，看完对method的本质理解更深了。（虽然也翻了好几遍go spec，但自己思考时没有意识到[instance.method(x,y)  function(instance, x,y)]这样的转换，还是理解不够深入）
再有一点是go func的执行，虽然go routine的执行时机不确定，但func的入参值是在执行go func时就确定的。类似的例子还有这个：https://play.golang.org/p/dOUFNj96EIQ

另外，对于 data1 := []*field{{&quot;one&quot;}, {&quot;two&quot;}, {&quot;three&quot;}} ，{&quot;one&quot;}明明是field类型的常量，但可以隐式转换为*field类型，翻了go spec 没找到解答的位置，真是无法释怀。</description>
		<content:encoded><![CDATA[<p>多谢解惑，看完对method的本质理解更深了。（虽然也翻了好几遍go spec，但自己思考时没有意识到[instance.method(x,y)  function(instance, x,y)]这样的转换，还是理解不够深入）<br />
再有一点是go func的执行，虽然go routine的执行时机不确定，但func的入参值是在执行go func时就确定的。类似的例子还有这个：https://play.golang.org/p/dOUFNj96EIQ</p>
<p>另外，对于 data1 := []*field{{“one”}, {“two”}, {“three”}} ，{“one”}明明是field类型的常量，但可以隐式转换为*field类型，翻了go spec 没找到解答的位置，真是无法释怀。</p>
]]></content:encoded>
	</item>
</channel>
</rss>
