<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:content="http://purl.org/rss/1.0/modules/content/">

  <channel>
    <title>inasayang&#39;s blog</title>
    <link>/</link>
    <description>Recent blog posts on inasayang&#39;s blog</description>
    
    <generator>Hugo (https://gohugo.io)</generator>
    
    <language>zh-cn</language>
    
    <managingEditor>xiayangzzw@gmail.com (inasayang)</managingEditor>
    
    <webMaster>xiayangzzw@gmail.com (inasayang)</webMaster>
    
    <lastBuildDate>Thu, 07 Aug 2025 00:00:00 Z</lastBuildDate>
    
    <atom:link href="/tags/go/index.xml" rel="self" type="application/rss+xml" />
    

    <item>
      <title>Go | First Response Pattern</title>
      <link>/posts/250807_gofirstresponsepattern/</link>
      <pubDate>Thu, 07 Aug 2025 00:00:00 Z</pubDate>
      
      <author>xiayangzzw@gmail.com (inasayang)</author>

      
      
      
      

      <description>
      
      </description>
      <content:encoded>&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// Avoid timeout - Replicate servers and use first response&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;type&lt;/span&gt; Result &lt;span style=&#34;color:#e78284&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;type&lt;/span&gt; Search &lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt;(query &lt;span style=&#34;color:#e78284&#34;&gt;string&lt;/span&gt;) Result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;fakeSearch&lt;/span&gt;(kind &lt;span style=&#34;color:#e78284&#34;&gt;string&lt;/span&gt;) Search {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ca9ee6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt;(query &lt;span style=&#34;color:#e78284&#34;&gt;string&lt;/span&gt;) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		time.&lt;span style=&#34;color:#8caaee&#34;&gt;Sleep&lt;/span&gt;(time.&lt;span style=&#34;color:#8caaee&#34;&gt;Duration&lt;/span&gt;(rand.&lt;span style=&#34;color:#8caaee&#34;&gt;Intn&lt;/span&gt;(&lt;span style=&#34;color:#ef9f76&#34;&gt;100&lt;/span&gt;)) &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;*&lt;/span&gt; time.Millisecond)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ca9ee6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;Result&lt;/span&gt;(fmt.&lt;span style=&#34;color:#8caaee&#34;&gt;Sprintf&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;%s result for %q&amp;#34;&lt;/span&gt;, kind, query))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;First&lt;/span&gt;(query &lt;span style=&#34;color:#e78284&#34;&gt;string&lt;/span&gt;, replicas &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;...&lt;/span&gt;Search) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	c &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#99d1db&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#e78284&#34;&gt;chan&lt;/span&gt; Result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	searchReplica &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt;(i &lt;span style=&#34;color:#e78284&#34;&gt;int&lt;/span&gt;) { c &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;lt;-&lt;/span&gt; replicas[i](query) }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ca9ee6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ca9ee6&#34;&gt;range&lt;/span&gt; replicas {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ca9ee6&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;searchReplica&lt;/span&gt;(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ca9ee6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;lt;-&lt;/span&gt;c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	start &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; time.&lt;span style=&#34;color:#8caaee&#34;&gt;Now&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	result &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;First&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;golang&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8caaee&#34;&gt;fakeSearch&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;replica1&amp;#34;&lt;/span&gt;), 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8caaee&#34;&gt;fakeSearch&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;replica2&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8caaee&#34;&gt;fakeSearch&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;replica3&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	elapsed &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; time.&lt;span style=&#34;color:#8caaee&#34;&gt;Since&lt;/span&gt;(start)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	fmt.&lt;span style=&#34;color:#8caaee&#34;&gt;Println&lt;/span&gt;(result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	fmt.&lt;span style=&#34;color:#8caaee&#34;&gt;Printf&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;%.3fms\n&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#99d1db&#34;&gt;float64&lt;/span&gt;(elapsed.&lt;span style=&#34;color:#8caaee&#34;&gt;Nanoseconds&lt;/span&gt;())&lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ef9f76&#34;&gt;1e6&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这是 Go 并发经典实践之一：“用副本竞速的方式避免超时，返回最早的可用结果”——常见于高可用分布式系统的请求快速返回（比如多个搜索副本、微服务副本集请谁先响应）。&lt;/p&gt;
&lt;h2 id=&#34;主要思想&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e4%b8%bb%e8%a6%81%e6%80%9d%e6%83%b3&#34;&gt;
        #
    &lt;/a&gt;
    主要思想
&lt;/div&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;业务背景&lt;/strong&gt;：你有好几个“备用服务器/副本/搜索实现”，哪个响应最快用哪个，“慢的都不用等”，避免整个请求因单点慢或偶发延迟变慢。&lt;/li&gt;
&lt;li&gt;这是现实世界中 Google、Amazon 等公司搜索引擎“边缘副本”、“异地容灾高可用”大量使用的技术方案。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;现实应用场景&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e7%8e%b0%e5%ae%9e%e5%ba%94%e7%94%a8%e5%9c%ba%e6%99%af&#34;&gt;
        #
    &lt;/a&gt;
    现实应用场景
&lt;/div&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;微服务多活&lt;/strong&gt;：多个服务副本响应同一请求，优先拿到第一个并快速返回，极大降低99.99延迟。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CDN/边缘计算&lt;/strong&gt;：拉取数据时向多节点并发请求，客户端只拿第一个响应的内容。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多家供应商比价/辅助搜索聚合&lt;/strong&gt;：哪个接口快就显示谁的内容。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;使用context控制goroutine-leak&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8context%e6%8e%a7%e5%88%b6goroutine-leak&#34;&gt;
        #
    &lt;/a&gt;
    使用context控制goroutine leak
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;这个简单写法确实会导致 goroutine 泄露（goroutine leak）的问题。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;你发起了多个副本 goroutine，每个都会做完自己的“搜索”然后把结果写入同一个 channel &lt;code&gt;c&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;但 &lt;code&gt;First&lt;/code&gt; 只从 channel 取第一个结果：&lt;code&gt;return &amp;lt;-c&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;其它 goroutine 后续写入 channel 时，如果没人读，&lt;strong&gt;它们会永远阻塞在 &lt;code&gt;c &amp;lt;- ...&lt;/code&gt; 这一行上&lt;/strong&gt;——此时这些 goroutine 无法退出，即内存泄露。&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;First&lt;/span&gt;(query &lt;span style=&#34;color:#e78284&#34;&gt;string&lt;/span&gt;, replicas &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;...&lt;/span&gt;Search) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	ctx, cancel &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; context.&lt;span style=&#34;color:#8caaee&#34;&gt;WithCancel&lt;/span&gt;(context.&lt;span style=&#34;color:#8caaee&#34;&gt;Background&lt;/span&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ca9ee6&#34;&gt;defer&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;cancel&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	c &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#99d1db&#34;&gt;make&lt;/span&gt;(&lt;span style=&#34;color:#e78284&#34;&gt;chan&lt;/span&gt; Result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	searchReplica &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt;(i &lt;span style=&#34;color:#e78284&#34;&gt;int&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ca9ee6&#34;&gt;select&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ca9ee6&#34;&gt;case&lt;/span&gt; c &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;lt;-&lt;/span&gt; replicas[i](query):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ca9ee6&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;lt;-&lt;/span&gt;ctx.&lt;span style=&#34;color:#8caaee&#34;&gt;Done&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ca9ee6&#34;&gt;return&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ca9ee6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ca9ee6&#34;&gt;range&lt;/span&gt; replicas {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ca9ee6&#34;&gt;go&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;searchReplica&lt;/span&gt;(i)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	result &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;lt;-&lt;/span&gt;c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8caaee&#34;&gt;cancel&lt;/span&gt;() &lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// 让其他 goroutine 自动退出&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ca9ee6&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;主流程一旦拿到第一个结果，cancel() 会通知其他所有 goroutine 退出。&lt;/p&gt;
&lt;p&gt;复杂情况下可配合 context、WaitGroup 做到无资源泄露。&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://www.concurrency.rocks/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;https://www.concurrency.rocks/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
      
      <category>go</category>
      
      
      <guid isPermaLink="true">/posts/250807_gofirstresponsepattern/</guid>
    </item>
    

    <item>
      <title>Go | 跨包访问非导出符号</title>
      <link>/posts/250421_call_unexported_fn_and_var/25_04_21_call_unexported_fn_and_var/</link>
      <pubDate>Mon, 21 Apr 2025 00:00:00 Z</pubDate>
      
      <author>xiayangzzw@gmail.com (inasayang)</author>

      
      
      
      

      <description>
      
      </description>
      <content:encoded>&lt;p&gt;&lt;code&gt;//go:linkname&lt;/code&gt; 是 &lt;code&gt;Go&lt;/code&gt; 语言中的一个编译指令（&lt;code&gt;compiler directive&lt;/code&gt;），用于在编译期间将一个符号（函数或变量）的名称重命名成另一个符号，达到在不同包之间绕过封装直接访问非导出（&lt;code&gt;unexported&lt;/code&gt;）标识符的效果。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;需要导入 &lt;code&gt;unsafe&lt;/code&gt; 包&lt;/li&gt;
&lt;li&gt;函数或变量必须声明&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;使用未导出函数示例1&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e6%9c%aa%e5%af%bc%e5%87%ba%e5%87%bd%e6%95%b0%e7%a4%ba%e4%be%8b1&#34;&gt;
        #
    &lt;/a&gt;
    使用未导出函数（示例1）：
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;package&lt;/span&gt; mypkg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;import&lt;/span&gt; _ &lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;unsafe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:linkname privateFunc runtime.internalFunc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;privateFunc&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里 &lt;code&gt;mypkg&lt;/code&gt; 包里的 &lt;code&gt;privateFunc&lt;/code&gt; 会被链接为 &lt;code&gt;runtime&lt;/code&gt; 包中的非导出函数 &lt;code&gt;internalFunc&lt;/code&gt;，调用&lt;code&gt;privateFunc()&lt;/code&gt; 就是调用的 &lt;code&gt;runtime.internalFunc()&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;使用未导出函数示例2&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e6%9c%aa%e5%af%bc%e5%87%ba%e5%87%bd%e6%95%b0%e7%a4%ba%e4%be%8b2&#34;&gt;
        #
    &lt;/a&gt;
    使用未导出函数（示例2）：
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;package&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _ &lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;unsafe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _ &lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;github.com/xxx/yyy/zzz&amp;#34;&lt;/span&gt;  &lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// 确保包被导入&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:linkname newUUID github.com/xxx/yyy/zzz.newUUID&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;newUUID&lt;/span&gt;() &lt;span style=&#34;color:#e78284&#34;&gt;string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    s &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;newUUID&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fmt.&lt;span style=&#34;color:#8caaee&#34;&gt;Println&lt;/span&gt;(s)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;使用未导出变量&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e6%9c%aa%e5%af%bc%e5%87%ba%e5%8f%98%e9%87%8f&#34;&gt;
        #
    &lt;/a&gt;
    使用未导出变量：
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;package&lt;/span&gt; yourpkg
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;import&lt;/span&gt; _ &lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;unsafe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:linkname someValue github.com/xxx/yyy/zzz.someValue&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;var&lt;/span&gt; someValue &lt;span style=&#34;color:#e78284&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded>
      
      <category>go</category>
      
      <category>unsafe</category>
      
      
      <guid isPermaLink="true">/posts/250421_call_unexported_fn_and_var/25_04_21_call_unexported_fn_and_var/</guid>
    </item>
    

    <item>
      <title>Go | 使用PGO优化编译示例</title>
      <link>/posts/250415_golangpgoexample/</link>
      <pubDate>Tue, 15 Apr 2025 00:00:00 Z</pubDate>
      
      <author>xiayangzzw@gmail.com (inasayang)</author>

      
      
      
      

      <description>
      
      </description>
      <content:encoded>&lt;p&gt;PGO (Profile-Guided Optimization) 是一种编译优化技术，通过收集程序的实际运行时数据来指导编译器进行更有针对性的优化。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-txt&#34; data-lang=&#34;txt&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-pgo file
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        specify the file path of a profile for profile-guided optimization (PGO).
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        When the special name &amp;#34;auto&amp;#34; is specified, for each main package in the
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        build, the go command selects a file named &amp;#34;default.pgo&amp;#34; in the package&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        directory if that file exists, and applies it to the (transitive)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        dependencies of the main package (other packages are not affected).
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        Special name &amp;#34;off&amp;#34; turns off PGO. The default is &amp;#34;auto&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段说明解释了 &lt;code&gt;-pgo&lt;/code&gt; 参数的几种用法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;pgo=文件路径&lt;/code&gt; - 指定一个具体的性能分析文件路径用于PGO优化&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pgo=auto&lt;/code&gt; - 自动模式(默认)，会在每个main包的目录中查找名为&amp;quot;default.pgo&amp;quot;的文件&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pgo=off&lt;/code&gt; - 明确关闭PGO优化&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;当使用自动模式时，PGO优化只会应用到main包及其依赖项，而不会影响其他不相关的包。&lt;/p&gt;
&lt;h2 id=&#34;收集性能分析数据&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e6%94%b6%e9%9b%86%e6%80%a7%e8%83%bd%e5%88%86%e6%9e%90%e6%95%b0%e6%8d%ae&#34;&gt;
        #
    &lt;/a&gt;
    收集性能分析数据
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// main.go&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;package&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#81c8be&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;os&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;runtime/pprof&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;computeIntensive&lt;/span&gt;() &lt;span style=&#34;color:#e78284&#34;&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ca9ee6&#34;&gt;for&lt;/span&gt; i &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;0&lt;/span&gt;; i &amp;lt; &lt;span style=&#34;color:#ef9f76&#34;&gt;10000000&lt;/span&gt;; i&lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        result &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;+=&lt;/span&gt; i &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;%&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ca9ee6&#34;&gt;return&lt;/span&gt; result
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// 第一次运行时开启性能分析&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ca9ee6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#99d1db&#34;&gt;len&lt;/span&gt;(os.Args) &amp;gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; os.Args[&lt;span style=&#34;color:#ef9f76&#34;&gt;1&lt;/span&gt;] &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;profile&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        f, _ &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; os.&lt;span style=&#34;color:#8caaee&#34;&gt;Create&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;profile.pprof&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ca9ee6&#34;&gt;defer&lt;/span&gt; f.&lt;span style=&#34;color:#8caaee&#34;&gt;Close&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        pprof.&lt;span style=&#34;color:#8caaee&#34;&gt;StartCPUProfile&lt;/span&gt;(f)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ca9ee6&#34;&gt;defer&lt;/span&gt; pprof.&lt;span style=&#34;color:#8caaee&#34;&gt;StopCPUProfile&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// 执行计算密集型操作&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    result &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#8caaee&#34;&gt;computeIntensive&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#99d1db&#34;&gt;println&lt;/span&gt;(&lt;span style=&#34;color:#a6d189&#34;&gt;&amp;#34;Result:&amp;#34;&lt;/span&gt;, result)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go build -o myapp.&lt;span style=&#34;color:#ef9f76&#34;&gt;exe&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./myapp.&lt;span style=&#34;color:#ef9f76&#34;&gt;exe&lt;/span&gt; profile
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;使用收集的分析数据进行优化编译&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e4%bd%bf%e7%94%a8%e6%94%b6%e9%9b%86%e7%9a%84%e5%88%86%e6%9e%90%e6%95%b0%e6%8d%ae%e8%bf%9b%e8%a1%8c%e4%bc%98%e5%8c%96%e7%bc%96%e8%af%91&#34;&gt;
        #
    &lt;/a&gt;
    使用收集的分析数据进行优化编译
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go build -pgo profile.&lt;span style=&#34;color:#ef9f76&#34;&gt;pprof&lt;/span&gt; -o myapp_optimized.&lt;span style=&#34;color:#ef9f76&#34;&gt;exe&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果有多个pprof文件&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;# 使用pprof工具合并多个分析文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go tool pprof -proto cpu1.&lt;span style=&#34;color:#ef9f76&#34;&gt;pprof&lt;/span&gt; cpu2.&lt;span style=&#34;color:#ef9f76&#34;&gt;pprof&lt;/span&gt; cpu3.&lt;span style=&#34;color:#ef9f76&#34;&gt;pprof&lt;/span&gt; &amp;gt; combined.&lt;span style=&#34;color:#ef9f76&#34;&gt;pprof&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;# 使用合并后的分析文件进行构建&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;go build -pgo combined.&lt;span style=&#34;color:#ef9f76&#34;&gt;pprof&lt;/span&gt; -o myapp_optimized.&lt;span style=&#34;color:#ef9f76&#34;&gt;exe&lt;/span&gt; .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;测试&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e6%b5%8b%e8%af%95&#34;&gt;
        #
    &lt;/a&gt;
    测试
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;time ./myapp.&lt;span style=&#34;color:#ef9f76&#34;&gt;exe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;time ./myapp_optimized.&lt;span style=&#34;color:#ef9f76&#34;&gt;exe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;PGO 优化通常在较大、复杂的应用中效果更显著，特别是有明显热点路径的程序。对于简单程序，优化效果可能不明显，甚至因为优化开销而略微变慢。&lt;/li&gt;
&lt;li&gt;PGO 主要适用于计算密集型应用。&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
      
      <category>go</category>
      
      <category>pgo</category>
      
      <category>compile</category>
      
      
      <guid isPermaLink="true">/posts/250415_golangpgoexample/</guid>
    </item>
    

    <item>
      <title>Go | 检测当前系统位数</title>
      <link>/posts/240309_gocheckosbits/</link>
      <pubDate>Sat, 09 Mar 2024 00:00:00 Z</pubDate>
      
      <author>xiayangzzw@gmail.com (inasayang)</author>

      
      
      
      

      <description>
      
      </description>
      <content:encoded>&lt;h2 id=&#34;声明一个常量来表示当前操作系统的位数&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e5%a3%b0%e6%98%8e%e4%b8%80%e4%b8%aa%e5%b8%b8%e9%87%8f%e6%9d%a5%e8%a1%a8%e7%a4%ba%e5%bd%93%e5%89%8d%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e7%9a%84%e4%bd%8d%e6%95%b0&#34;&gt;
        #
    &lt;/a&gt;
    声明一个常量来表示当前操作系统的位数
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;const&lt;/span&gt; NativeWordBits = &lt;span style=&#34;color:#ef9f76&#34;&gt;32&lt;/span&gt; &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; (^&lt;span style=&#34;color:#99d1db&#34;&gt;uint&lt;/span&gt;(&lt;span style=&#34;color:#ef9f76&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;63&lt;/span&gt;) &lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// 64 or 32 &lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;^uint(0)&lt;/code&gt;：对于无符号整型 uint(0)（其所有位都是0），按位取反操作会产生一个所有位都是1的数字。这个结果的数值上等同于 uint 能表示的最大值。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&amp;gt; 63&lt;/code&gt;：这个操作的结果依赖于 uint 的大小：
&lt;ul&gt;
&lt;li&gt;在64位平台上，uint 类型为64位，&lt;code&gt;^uint(0)&lt;/code&gt; 产生一个所有位都为1的64位数字。向右移动63位后，最左边的一位（最高位）会移动到最右边，结果为1（二进制的000&amp;hellip;001）&lt;/li&gt;
&lt;li&gt;在32位平台上，尽管仍然执行相同的操作，但是由于 uint 的大小只有32位，所以这个操作实际上产生的结果是 0，因为32位无法表示一个向右移动了63位的值&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;32 &amp;lt;&amp;lt; (... &amp;gt;&amp;gt; 63)&lt;/code&gt;：最终这个表达式将32左移上一步的结果。在32位平台上，由于上一步的结果是 0，&lt;code&gt;32 &amp;lt;&amp;lt; 0&lt;/code&gt; 保持不变，仍然是 32。这反映了32位系统的字长。在64位平台上，上一步的结果是 1，因此 &lt;code&gt;32 &amp;lt;&amp;lt; 1&lt;/code&gt; 相当于将32乘以2，结果是 64。这反映了64位系统的字长。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;检查当前操作系统是32位的还是64位的&#34; &gt;
&lt;div&gt;
    &lt;a href=&#34;#%e6%a3%80%e6%9f%a5%e5%bd%93%e5%89%8d%e6%93%8d%e4%bd%9c%e7%b3%bb%e7%bb%9f%e6%98%af32%e4%bd%8d%e7%9a%84%e8%bf%98%e6%98%af64%e4%bd%8d%e7%9a%84&#34;&gt;
        #
    &lt;/a&gt;
    检查当前操作系统是32位的还是64位的
&lt;/div&gt;
&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;const&lt;/span&gt; Is64bitOS = ^&lt;span style=&#34;color:#99d1db&#34;&gt;uint&lt;/span&gt;(&lt;span style=&#34;color:#ef9f76&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;63&lt;/span&gt; &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e78284&#34;&gt;const&lt;/span&gt; Is32bitOS = ^&lt;span style=&#34;color:#99d1db&#34;&gt;uint&lt;/span&gt;(&lt;span style=&#34;color:#ef9f76&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;32&lt;/span&gt; &lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ef9f76&#34;&gt;0&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Go101&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
      
      <category>go</category>
      
      <category>bitwise</category>
      
      
      <guid isPermaLink="true">/posts/240309_gocheckosbits/</guid>
    </item>
    

    <item>
      <title>Go | 使一个结构体类型不可比较</title>
      <link>/posts/230808_gomakestructnotcompare/</link>
      <pubDate>Tue, 08 Aug 2023 00:00:00 Z</pubDate>
      
      <author>xiayangzzw@gmail.com (inasayang)</author>

      
      
      
      

      <description>
      
      </description>
      <content:encoded>&lt;p&gt;可以放置一个非导出的零尺寸的不可比较类型的字段在结构体类型中以使此结构体类型不可比较&lt;/p&gt;
&lt;p&gt;结构体&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;type T struct {
	dummy [0]func()
	AnotherField int
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;使用&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;var x map[T]int // 编译错误：非法的键值类型

var a, b T
_ = a == b // 编译错误：非法的比较
&lt;/code&gt;&lt;/pre&gt;</content:encoded>
      
      <category>go</category>
      
      <category>struct</category>
      
      
      <guid isPermaLink="true">/posts/230808_gomakestructnotcompare/</guid>
    </item>
    

    <item>
      <title>Go | 0尺寸结构体</title>
      <link>/posts/230807_gozerostruct/</link>
      <pubDate>Mon, 07 Aug 2023 00:00:00 Z</pubDate>
      
      <author>xiayangzzw@gmail.com (inasayang)</author>

      
      
      
      

      <description>
      
      </description>
      <content:encoded>&lt;p&gt;下面四个结构体的尺寸大小各是多少？&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;type A struct {
	x int64
	y int64
}
type A1 struct {
	x int64
	y int64
	z struct{}
}
type A2 struct {
	z struct{}
	x int64
	y int64
}
type A3 struct {
	x int64
	z struct{}
	y int64
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;答案&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;A： 16
A1： 24
A2： 16
A3： 16
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;为什么A1的结构体会不同呢？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个可寻址的结构值的所有字段都可以被取地址，A1可以被取地址，则z也可以被取地址&lt;/li&gt;
&lt;li&gt;如果非零尺寸的结构体值的最后一个字段的尺寸是零，那么取此最后一个字段的地址将会返回一个越出了结构体值分配的内存块的地址（可能指向另一个被分配的内存块）&lt;/li&gt;
&lt;li&gt;标准的Go编译器会确保取一个非零尺寸的结构体值的最后一个字段的地址时，绝对不会返回越出分配给此结构体值的内存块的地址&lt;/li&gt;
&lt;li&gt;Go标准编译器通过在需要时在结构体最后的零尺寸字段之后填充一些字节来实现这一点
&lt;ul&gt;
&lt;li&gt;具体补多少，需要达到内存对齐即可&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;如果一个结构体的全部字段的类型都是零尺寸的(因此整个结构体也是零尺寸的)，那么就不需要再填充字节，因为标准编译器会专门处理零尺寸的内存块&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;Golang101&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
      
      <category>go</category>
      
      
      <guid isPermaLink="true">/posts/230807_gozerostruct/</guid>
    </item>
    

    <item>
      <title>Go | Build Constraints 构建约束</title>
      <link>/posts/230102_gobuildconstraints/</link>
      <pubDate>Mon, 02 Jan 2023 00:00:00 Z</pubDate>
      
      <author>xiayangzzw@gmail.com (inasayang)</author>

      
      
      
      

      <description>
      一个构建约束(构建标签)是文件应包含在包中的条件。构建约束由开始的行注释给出。

      </description>
      <content:encoded>&lt;p&gt;一个构建约束(构建标签)是文件应包含在包中的条件。构建约束由开始的行注释给出。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;约束可以出现在任何类型的源文件中（不仅仅是 Go），但它们必须出现在文件顶部附近，前面只有空行和其他行注释。
这些规则意味着在 Go 文件中，构建约束必须出现在 package 子句之前。&lt;/p&gt;
&lt;p&gt;为了区分构建约束和包文档，构建约束后面应该跟一个空行。&lt;/p&gt;
&lt;p&gt;构建约束注释被评估为包含由 ||、&amp;amp;&amp;amp; 和 ! 组合的构建标记的表达式,运算符和括号。&lt;/p&gt;
&lt;p&gt;例如，当满足&lt;code&gt;linux&lt;/code&gt;和&lt;code&gt;386&lt;/code&gt;约束时，或者满足&lt;code&gt;darwin&lt;/code&gt;而&lt;code&gt;cgo&lt;/code&gt;不满足时，以下构建约束约束文件构建：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:build (linux &amp;amp;&amp;amp; 386) || (darwin &amp;amp;&amp;amp; !cgo)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一个文件有多个 &lt;code&gt;//go:build&lt;/code&gt; 行是错误的。&lt;/p&gt;
&lt;p&gt;在特定构建期间，满足以下构建标签：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;目标操作系统，由 &lt;code&gt;runtime.GOOS&lt;/code&gt; 拼写，使用 &lt;code&gt;GOOS&lt;/code&gt; 环境变量设置。&lt;/li&gt;
&lt;li&gt;目标体系结构，由 &lt;code&gt;runtime.GOARCH&lt;/code&gt; 拼写，使用 &lt;code&gt;GOARCH&lt;/code&gt; 环境变量设置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unix&lt;/code&gt;，如果 &lt;code&gt;GOOS&lt;/code&gt; 是 &lt;code&gt;Unix&lt;/code&gt; 或类 &lt;code&gt;Unix&lt;/code&gt; 系统。&lt;/li&gt;
&lt;li&gt;正在使用的编译器，&lt;code&gt;gc&lt;/code&gt;或&lt;code&gt;gccgo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cgo&lt;/code&gt;，如果支持 &lt;code&gt;cgo&lt;/code&gt; 命令（请参阅&lt;code&gt;go help environment&lt;/code&gt;中的 &lt;code&gt;CGO_ENABLED&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;每个 Go 主要版本的术语，通过当前版本：从 Go 1.1 版开始的“go1.1”，从 Go 1.12 开始的“go1.12”，等等。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-tags&lt;/code&gt; 标志给出的任何附加标签（参见&lt;code&gt;go help build&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果文件名在去除扩展名和可能的 &lt;code&gt;_test&lt;/code&gt; 后缀后匹配以下任何模式：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;*&lt;/span&gt;_GOOS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;*&lt;/span&gt;_GOARCH
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#99d1db;font-weight:bold&#34;&gt;*&lt;/span&gt;_GOOS_GOARCH
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;（示例：&lt;code&gt;source_windows_amd64.go&lt;/code&gt;）其中 &lt;code&gt;GOOS&lt;/code&gt; 和 &lt;code&gt;GOARCH&lt;/code&gt; 分别代表任何已知的操作系统和体系结构值，然后该文件被认为具有需要这些术语的隐式构建约束（除了文件中的任何显式约束之外）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;除了 &lt;code&gt;android&lt;/code&gt; 标签和文件之外，使用 &lt;code&gt;GOOS=android&lt;/code&gt; 匹配构建标签和文件，就像 &lt;code&gt;GOOS=linux&lt;/code&gt; 一样。&lt;/li&gt;
&lt;li&gt;除了 &lt;code&gt;illumos&lt;/code&gt; 标签和文件之外，使用 &lt;code&gt;GOOS=illumos&lt;/code&gt; 匹配构建标签和文件，就像 &lt;code&gt;GOOS=solaris&lt;/code&gt; 一样。&lt;/li&gt;
&lt;li&gt;除了 &lt;code&gt;ios&lt;/code&gt; 标签和文件之外，使用 &lt;code&gt;GOOS=ios&lt;/code&gt; 匹配构建标签和文件，就像 &lt;code&gt;GOOS=darwin&lt;/code&gt; 一样。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;要阻止文件被考虑用于构建：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:build ignore&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;仅在使用 &lt;code&gt;cgo&lt;/code&gt; 时构建文件，并且仅在 &lt;code&gt;Linux&lt;/code&gt; 和 &lt;code&gt;OS X&lt;/code&gt; 上：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:build cgo &amp;amp;&amp;amp; (linux || darwin)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样的文件通常与另一个实现其他系统默认功能的文件配对，在这种情况下会带有约束：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;//go:build !(cgo &amp;amp;&amp;amp; (linux || darwin))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;将文件命名为 &lt;code&gt;dns_windows.go&lt;/code&gt; 将导致它仅在为 &lt;code&gt;Windows&lt;/code&gt; 构建包时被包含；同样，只有在为 32 位 &lt;code&gt;x86&lt;/code&gt; 构建包时才会包含 &lt;code&gt;math_386.s&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Go 版本 1.16 及更早版本使用不同的语法来构建约束，带有&lt;code&gt;// +build&lt;/code&gt;前缀。 gofmt 命令将在遇到旧语法时添加等效的 &lt;code&gt;//go:build&lt;/code&gt; 约束。&lt;/p&gt;
&lt;p&gt;例外，下列使用空格，逗号，多行在新版本中已失效：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用空格分隔的构建标记在逻辑上是或
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// +build linux darwin&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;用逗号分隔的构建标记在逻辑上是和
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// +build windows,386&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;在多行上构建约束是逻辑和
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#c6d0f5;background-color:#303446;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// +build windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#737994;font-style:italic&#34;&gt;// +build 386&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;完整的约束标签可以在&lt;a href=&#34;https://github.com/golang/go/blob/master/src/go/build/syslist.go&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;这里&lt;/a&gt;找到&lt;/p&gt;
&lt;hr&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://pkg.go.dev/cmd/go#hdr-Build_constraints&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Build constraints&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded>
      
      <category>go</category>
      
      <category>compile</category>
      
      
      <guid isPermaLink="true">/posts/230102_gobuildconstraints/</guid>
    </item>
    
  </channel>
</rss>
