<?xml version="1.0" encoding="utf-8"?>






<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
        <title>JJMeg&#39;s blog</title>
        <link>https://jjmeg.github.io/</link>
        <description>MemE 是一个强大且可高度定制的 GoHugo 博客主题，专为个人博客设计。</description>
        <generator>Hugo 0.74.3 https://gohugo.io/</generator>
        
            <language>zh-CN</language>
        
        
            <managingEditor>jjmeg.he@gmail.com (JJMeg)</managingEditor>
        
        
            <webMaster>jjmeg.he@gmail.com (JJMeg)</webMaster>
        
        
            <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
        
        <lastBuildDate>Tue, 22 Sep 2020 23:28:26 +0800</lastBuildDate>
        
            <atom:link rel="self" type="application/rss+xml" href="https://jjmeg.github.io/rss.xml" />
        
        
            <item>
                <title>2020三季度</title>
                <link>https://jjmeg.github.io/posts/2020-autumn/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/2020-autumn/</guid>
                <pubDate>Tue, 22 Sep 2020 20:24:37 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[<p><center>🕛</center></p>

<p style="text-indent:2em">2020年的第三季度，发生了很多事情，同事们相继离职，架构变动，经历二次架构变动，害，都挤在这个季度爆发了；</p>
<p style="text-indent:2em">当然，我也如愿争取到新的机会，进入新的团队，和一年前的完全不一样的技术栈，在这一个季度内，完成了0-1的重构项目，想想人还是需要压力的；</p>
<p style="text-indent:2em">回顾前一年的业务和技术，思考越来越少，近三个月，我终于体会到别人说的做业务很累，on call嘛，害，有点享受这种忙碌的状态；</p>
<p style="text-indent:2em">如愿的回到喜欢的方向，因为一年的技术上的gap，加了很多班调整适应，如愿加班，就是这个感觉吧；</p>
<p style="text-indent:2em">一整年思考缓慢，突然忙起来还有些不太适应；</p>
<p style="text-indent:2em">脾气好了嘛？- 没有</p>
<p style="text-indent:2em">做事井井有条了嘛？- 有一点吧</p>
<p style="text-indent:2em">现在最缺的就是觉了吧。</p>

<p style="text-indent:2em">2020年第四季度</p>
<p style="text-indent:2em">Enjoy it!</p>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E7%A2%8E%E5%BF%B5/">碎念</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>FastJson 反序列化部分字段为 Null</title>
                <link>https://jjmeg.github.io/posts/fastjson-field-null/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/fastjson-field-null/</guid>
                <pubDate>Mon, 20 Jul 2020 18:25:51 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>⚠ 使用 FastJson 将 json 文件反序列化为 JavaBean 出现字段缺失 ⚠</center></p>

<h3 id="问题复现">问题复现</h3>

<p>FastJson 版本：1.2.70</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-xml" data-lang="xml"><span class="nt">&lt;dependency&gt;</span>
    <span class="nt">&lt;groupId&gt;</span>com.alibaba<span class="nt">&lt;/groupId&gt;</span>
    <span class="nt">&lt;artifactId&gt;</span>fastjson<span class="nt">&lt;/artifactId&gt;</span>
    <span class="nt">&lt;version&gt;</span>1.2.70<span class="nt">&lt;/version&gt;</span>
<span class="nt">&lt;/dependency&gt;</span></code></pre></td></tr></table>
</div>
</div>
<p>json 内容</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-json" data-lang="json"><span class="p">{</span>
  <span class="nt">&#34;properties&#34;</span><span class="p">:</span> <span class="p">{</span>
    <span class="nt">&#34;jobName&#34;</span><span class="p">:</span> <span class="s2">&#34;this_is_a_test&#34;</span><span class="p">,</span>
    <span class="nt">&#34;description&#34;</span><span class="p">:</span> <span class="s2">&#34;for test json&#34;</span>
  <span class="p">},</span>
  <span class="nt">&#34;task&#34;</span><span class="p">:</span> <span class="p">[</span>
    <span class="p">{</span>
      <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;task_1&#34;</span><span class="p">,</span>
      <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;test&#34;</span><span class="p">,</span>
      <span class="nt">&#34;className&#34;</span><span class="p">:</span> <span class="s2">&#34;com.jjmeg.Task&#34;</span><span class="p">,</span>
      <span class="nt">&#34;args&#34;</span><span class="p">:</span> <span class="p">{</span>
        <span class="nt">&#34;topic&#34;</span><span class="p">:</span> <span class="s2">&#34;mockTopic&#34;</span><span class="p">,</span>
        <span class="nt">&#34;username&#34;</span><span class="p">:</span> <span class="s2">&#34;mockPin&#34;</span><span class="p">,</span>
        <span class="nt">&#34;password&#34;</span><span class="p">:</span> <span class="s2">&#34;mockPasswd&#34;</span>
      <span class="p">}</span>
    <span class="p">}</span>
  <span class="p">]</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>设计的 JavaBean：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Flow</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">properties</span><span class="o">;</span>
    <span class="kd">public</span> <span class="n">List</span><span class="o">&lt;</span><span class="n">Task</span><span class="o">&gt;</span> <span class="n">task</span><span class="o">;</span>

    <span class="nd">@Override</span>
    <span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="o">{</span>
        <span class="k">return</span> <span class="s">&#34;Flow{&#34;</span> <span class="o">+</span>
                <span class="s">&#34;properties=&#39;&#34;</span> <span class="o">+</span> <span class="n">properties</span> <span class="o">+</span> <span class="sc">&#39;\&#39;&#39;</span> <span class="o">+</span>
                <span class="s">&#34;, task=&#39;&#34;</span> <span class="o">+</span> <span class="n">task</span> <span class="o">+</span><span class="sc">&#39;\&#39;&#39;</span> <span class="o">+</span>
                <span class="sc">&#39;}&#39;</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Task</span> <span class="kd">implements</span> <span class="n">Serializable</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="n">String</span> <span class="n">name</span><span class="o">;</span>

    <span class="kd">public</span> <span class="n">String</span> <span class="n">type</span><span class="o">;</span>

    <span class="kd">public</span> <span class="n">String</span> <span class="n">className</span><span class="o">;</span>

    <span class="kd">public</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">args</span><span class="o">;</span>

    <span class="c1">// 含参构造函数、无默认构造函数
</span><span class="c1"></span>    <span class="kd">public</span> <span class="nf">Task</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">ConfigurationException</span><span class="o">,</span> <span class="n">IOException</span> <span class="o">{</span>
        <span class="n">String</span> <span class="n">text</span> <span class="o">=</span> <span class="n">IOUtils</span><span class="o">.</span><span class="na">toString</span><span class="o">(</span><span class="k">new</span> <span class="n">FileInputStream</span><span class="o">(</span><span class="n">filePath</span><span class="o">),</span> <span class="n">StandardCharsets</span><span class="o">.</span><span class="na">UTF_8</span><span class="o">);</span>
        <span class="n">Flow</span> <span class="n">flow</span> <span class="o">=</span> <span class="n">JSON</span><span class="o">.</span><span class="na">parseObject</span><span class="o">(</span><span class="n">text</span><span class="o">,</span> <span class="n">Flow</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<p>运行结果中，Task的内容有缺失：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Task<span class="o">{</span><span class="nv">name</span><span class="o">=</span><span class="s1">&#39;task_1&#39;</span>, <span class="nv">type</span><span class="o">=</span><span class="s1">&#39;null&#39;</span>, <span class="nv">className</span><span class="o">=</span><span class="s1">&#39;null&#39;</span>, <span class="nv">args</span><span class="o">=</span>null<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="问题原因">问题原因：</h3>

<p>FastJson 反序列过程中，使用默认的构造函数创建实例，在没有默认构造函数情况下，FastJson 使用含参的构造函数。</p>

<p>在 <code>Task</code> 类中，构造函数被重写为 <code>Task(String name)</code>，则只有 <code>name</code> 字段被赋值，同理，该示例中，只定义含三个参数的构造函数 <code>public Task(String name, String className, String type)</code> ，反序列化的 <code>Task</code> 对象的 <code>args</code> 属性为 <code>null</code>。</p>

<h3 id="解决办法">解决办法：</h3>

<p>添加无参构造函数或含所有参数的构造函数</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Java" data-lang="Java"><span class="c1">// 无参函数
</span><span class="c1"></span><span class="kd">public</span> <span class="nf">Task</span><span class="o">()</span> <span class="o">{</span>
<span class="o">}</span>

<span class="c1">// 含所有参数的构造函数
</span><span class="c1"></span><span class="kd">public</span> <span class="nf">Task</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">String</span> <span class="n">className</span><span class="o">,</span> <span class="n">String</span> <span class="n">type</span><span class="o">,</span> <span class="n">Map</span><span class="o">&lt;</span><span class="n">String</span><span class="o">,</span> <span class="n">String</span><span class="o">&gt;</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
    <span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
    <span class="k">this</span><span class="o">.</span><span class="na">args</span> <span class="o">=</span> <span class="n">args</span><span class="o">;</span>
    <span class="k">this</span><span class="o">.</span><span class="na">type</span> <span class="o">=</span> <span class="n">type</span><span class="o">;</span>
    <span class="k">this</span><span class="o">.</span><span class="na">className</span> <span class="o">=</span> <span class="n">className</span><span class="o">;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<script src="https://utteranc.es/client.js"
        repo="JJMeg/jjmeg.io.comment"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
            <item>
                <title>InnoDB 与 MyISAM 区别及适用场景</title>
                <link>https://jjmeg.github.io/posts/inter/mysql/innodb-myisam-scene/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/inter/mysql/innodb-myisam-scene/</guid>
                <pubDate>Thu, 28 May 2020 13:22:47 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<h3 id="1-索引结构">1. 索引结构</h3>

<p>InnoDB 和 MyISAM 都使用 B+ 树作为索引结构，区别在于叶子节点：</p>

<ul>
<li>MyISAM 的叶子节点存储的是数据记录所在的地址，MyISAM 存储数据有索引文件及数据文件，先在索引文件内找到数据的地址，<strong>称为非聚集索引</strong>，再到数据文件内找到具体的文件记录</li>
<li>InnoDB索引文件就是数据文件，主索引树的叶子节点存储的是行数据的数据页，页内存储了完整的行数据记录，<strong>称为聚集索引</strong>，辅助索引树叶子节点存储主键值</li>
</ul>

<h3 id="2-事务-锁处理及外键支持的区别">2. 事务、锁处理及外键支持的区别</h3>

<table>
<thead>
<tr>
<th></th>
<th align="center">InnoDB</th>
<th align="center">MyISAM</th>
</tr>
</thead>

<tbody>
<tr>
<td>事务处理</td>
<td align="center">事务安全</td>
<td align="center">非事务安全</td>
</tr>

<tr>
<td>锁级别</td>
<td align="center">行锁和表锁</td>
<td align="center">表锁</td>
</tr>

<tr>
<td>外键支持</td>
<td align="center">支持</td>
<td align="center">不支持</td>
</tr>
</tbody>
</table>

<h3 id="3-查询效率">3. 查询效率</h3>

<table>
<thead>
<tr>
<th align="center">InnoDB</th>
<th align="center">MyISAM</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">慢</td>
<td align="center">快</td>
</tr>
</tbody>
</table>

<p>原因：</p>

<ul>
<li>InnoDB要加载数据页到缓存内，MyISAM只缓存索引块，MyISAM较少的磁盘io</li>
<li>InnoDB映射到数据页、到行，MyISAM记录文件的offset，定位比InnoDB快</li>
<li>InnoDB需要维护版本并发控制</li>
</ul>

<h3 id="4-适用场景">4. 适用场景</h3>

<table>
<thead>
<tr>
<th align="center">InnoDB</th>
<th align="center">MyISAM</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">多读多写</td>
<td align="center">多读少写</td>
</tr>

<tr>
<td align="center">有事务</td>
<td align="center">无事务</td>
</tr>

<tr>
<td align="center">高并发</td>
<td align="center">非高并发</td>
</tr>
</tbody>
</table>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/mysql/">MySQL</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/myisam/">MyISAM</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Kafka客户端--Go版本</title>
                <link>https://jjmeg.github.io/posts/kafka-golang-client/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/kafka-golang-client/</guid>
                <pubDate>Wed, 06 May 2020 20:56:46 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「 Kafka 」</center>
分布式消息平台，用Scala实现，本项目使用Go语言实现简单的消息生产和消费。</p>

<h3 id="kafka-客户端-golang-版">Kafka 客户端 Golang 版</h3>

<table>
<thead>
<tr>
<th>project</th>
<th>feature</th>
<th>weakness</th>
</tr>
</thead>

<tbody>
<tr>
<td><a href="https://shopify.github.io/sarama">Shopify/sarama</a></td>
<td>最受欢迎</td>
<td>集群式消费难实现，不支持Context</td>
</tr>

<tr>
<td><a href="https://github.com/bsm/sarama-cluster">bsm/sarama-cluster</a></td>
<td>基于sarama补充集群式消费</td>
<td>不支持Context</td>
</tr>

<tr>
<td><a href="https://github.com/confluentinc/confluent-kafka-go">confluentinc/confluent-kafka-go</a></td>
<td></td>
<td>依赖C语言库，不支持Context</td>
</tr>

<tr>
<td><a href="https://github.com/lovoo/goka">lovoo/goka</a></td>
<td>依赖于sarama</td>
<td>不支持Context</td>
</tr>

<tr>
<td><a href="https://github.com/segmentio/kafka-go">segmentio/kafka-go</a></td>
<td>同时支持集群模式，易与软件交互</td>
<td>未正式发布，支持Context</td>
</tr>
</tbody>
</table>

<hr />

<p>下面将基于 <a href="https://github.com/Shopify/sarama" target="_blank">Shopify/sarama</a>  实现简单的消费者及生产者。</p>

<h3 id="基本数据结构">基本数据结构</h3>

<ul>
<li><p>Reporter
生产者：包含一个Producer及一个logger用于日志记录</p></li>

<li><p>Subscriber
消费者：包含一个Consumer及logger
具体实现</p></li>
</ul>

<h3 id="生产者">生产者</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span><span class="lnt">64
</span><span class="lnt">65
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">reporter</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;github.com/Shopify/sarama&#34;</span>
	<span class="s">&#34;github.com/sirupsen/logrus&#34;</span>

	<span class="s">&#34;../error_const&#34;</span>
<span class="p">)</span>

<span class="c1">// kafka server 端配置
</span><span class="c1"></span><span class="kd">type</span> <span class="nx">KafkaCfg</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Host</span>  <span class="kt">string</span> <span class="s">`json:&#34;host&#34;`</span>
	<span class="nx">Topic</span> <span class="kt">string</span> <span class="s">`json:&#34;topic&#34;`</span>
<span class="p">}</span>

<span class="c1">// 消息生产者数据结构
</span><span class="c1"></span><span class="kd">type</span> <span class="nx">Reporter</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Producer</span> <span class="nx">sarama</span><span class="p">.</span><span class="nx">SyncProducer</span>
	<span class="nx">logger</span>   <span class="o">*</span><span class="nx">logrus</span><span class="p">.</span><span class="nx">Logger</span>
<span class="p">}</span>

<span class="c1">// 构造函数
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">NewReporter</span><span class="p">(</span><span class="nx">cfg</span> <span class="o">*</span><span class="nx">KafkaCfg</span><span class="p">,</span> <span class="nx">log</span> <span class="o">*</span><span class="nx">logrus</span><span class="p">.</span><span class="nx">Logger</span><span class="p">)</span> <span class="o">*</span><span class="nx">Reporter</span> <span class="p">{</span>
	<span class="nx">reporter</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">Reporter</span><span class="p">{</span>
		<span class="nx">logger</span><span class="p">:</span> <span class="nx">log</span><span class="p">,</span>
	<span class="p">}</span>

	<span class="nx">reporter</span><span class="p">.</span><span class="nf">setProducer</span><span class="p">(</span><span class="nx">cfg</span><span class="p">)</span>
	<span class="k">return</span> <span class="nx">reporter</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">reporter</span> <span class="o">*</span><span class="nx">Reporter</span><span class="p">)</span> <span class="nf">setProducer</span><span class="p">(</span><span class="nx">cfg</span> <span class="o">*</span><span class="nx">KafkaCfg</span><span class="p">)</span> <span class="p">{</span>
	<span class="kd">var</span> <span class="nx">broker</span> <span class="p">=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="nx">cfg</span><span class="p">.</span><span class="nx">Host</span><span class="p">}</span>

	<span class="nx">config</span> <span class="o">:=</span> <span class="nx">sarama</span><span class="p">.</span><span class="nf">NewConfig</span><span class="p">()</span>
	<span class="nx">config</span><span class="p">.</span><span class="nx">Producer</span><span class="p">.</span><span class="nx">Return</span><span class="p">.</span><span class="nx">Successes</span> <span class="p">=</span> <span class="kc">true</span>
	<span class="c1">// new 一个Producer
</span><span class="c1"></span>	<span class="nx">producer</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sarama</span><span class="p">.</span><span class="nf">NewSyncProducer</span><span class="p">(</span><span class="nx">broker</span><span class="p">,</span> <span class="nx">config</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">reporter</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="nx">error_const</span><span class="p">.</span><span class="nx">InitProducerError</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="nx">reporter</span><span class="p">.</span><span class="nx">Producer</span> <span class="p">=</span> <span class="nx">producer</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">reporter</span> <span class="o">*</span><span class="nx">Reporter</span><span class="p">)</span> <span class="nf">DoReport</span><span class="p">(</span><span class="nx">topic</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="p">{</span>
	<span class="nx">reporter</span><span class="p">.</span><span class="nf">do</span><span class="p">(</span><span class="nx">topic</span><span class="p">,</span> <span class="nx">msg</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">reporter</span> <span class="o">*</span><span class="nx">Reporter</span><span class="p">)</span> <span class="nf">do</span><span class="p">(</span><span class="nx">topic</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="p">{</span>
	<span class="nx">kafkaMsg</span> <span class="o">:=</span> <span class="nf">generateProducerMessage</span><span class="p">(</span><span class="nx">topic</span><span class="p">,</span> <span class="nx">msg</span><span class="p">)</span>
	<span class="nx">_</span><span class="p">,</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">reporter</span><span class="p">.</span><span class="nx">Producer</span><span class="p">.</span><span class="nf">SendMessage</span><span class="p">(</span><span class="nx">kafkaMsg</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">reporter</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="nx">error_const</span><span class="p">.</span><span class="nx">ReportKafkaMsgError</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nb">string</span><span class="p">(</span><span class="nx">msg</span><span class="p">))</span>
	<span class="p">}</span>
	<span class="nx">reporter</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nf">Infof</span><span class="p">(</span><span class="nx">error_const</span><span class="p">.</span><span class="nx">ReportKafkaMsgSuccess</span><span class="p">,</span> <span class="nb">string</span><span class="p">(</span><span class="nx">msg</span><span class="p">))</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">generateProducerMessage</span><span class="p">(</span><span class="nx">topic</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">message</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="o">*</span><span class="nx">sarama</span><span class="p">.</span><span class="nx">ProducerMessage</span> <span class="p">{</span>
	<span class="k">return</span> <span class="o">&amp;</span><span class="nx">sarama</span><span class="p">.</span><span class="nx">ProducerMessage</span><span class="p">{</span>
		<span class="nx">Topic</span><span class="p">:</span>     <span class="nx">topic</span><span class="p">,</span>
		<span class="nx">Partition</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
		<span class="nx">Value</span><span class="p">:</span>     <span class="nx">sarama</span><span class="p">.</span><span class="nf">StringEncoder</span><span class="p">(</span><span class="nx">message</span><span class="p">),</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="消费者">消费者</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">subscriber</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;github.com/Shopify/sarama&#34;</span>
	<span class="s">&#34;github.com/sirupsen/logrus&#34;</span>

	<span class="s">&#34;../error_const&#34;</span>
	<span class="s">&#34;../reporter&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">Subscriber</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Consumer</span> <span class="nx">sarama</span><span class="p">.</span><span class="nx">Consumer</span>
	<span class="nx">logger</span>   <span class="o">*</span><span class="nx">logrus</span><span class="p">.</span><span class="nx">Logger</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">NewSubscriber</span><span class="p">(</span><span class="nx">cfg</span> <span class="o">*</span><span class="nx">reporter</span><span class="p">.</span><span class="nx">KafkaCfg</span><span class="p">,</span> <span class="nx">log</span> <span class="o">*</span><span class="nx">logrus</span><span class="p">.</span><span class="nx">Logger</span><span class="p">)</span> <span class="o">*</span><span class="nx">Subscriber</span> <span class="p">{</span>
	<span class="nx">subscriber</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">Subscriber</span><span class="p">{</span>
		<span class="nx">logger</span><span class="p">:</span> <span class="nx">log</span><span class="p">,</span>
	<span class="p">}</span>
	<span class="nx">subscriber</span><span class="p">.</span><span class="nf">setConsumer</span><span class="p">(</span><span class="nx">cfg</span><span class="p">)</span>
	<span class="k">return</span> <span class="nx">subscriber</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">subscriber</span> <span class="o">*</span><span class="nx">Subscriber</span><span class="p">)</span> <span class="nf">setConsumer</span><span class="p">(</span><span class="nx">cfg</span> <span class="o">*</span><span class="nx">reporter</span><span class="p">.</span><span class="nx">KafkaCfg</span><span class="p">)</span> <span class="p">{</span>
	<span class="nx">consumer</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">sarama</span><span class="p">.</span><span class="nf">NewConsumer</span><span class="p">([]</span><span class="kt">string</span><span class="p">{</span><span class="nx">cfg</span><span class="p">.</span><span class="nx">Host</span><span class="p">},</span> <span class="kc">nil</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nb">panic</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">subscriber</span><span class="p">.</span><span class="nx">Consumer</span> <span class="p">=</span> <span class="nx">consumer</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">subscriber</span> <span class="o">*</span><span class="nx">Subscriber</span><span class="p">)</span> <span class="nf">Consume</span><span class="p">(</span><span class="nx">topic</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">ch</span> <span class="kd">chan</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">defer</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
		<span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">subscriber</span><span class="p">.</span><span class="nx">Consumer</span><span class="p">.</span><span class="nf">Close</span><span class="p">();</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
			<span class="nx">subscriber</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="nx">error_const</span><span class="p">.</span><span class="nx">SubcriberCloseConsumerError</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}()</span>

	<span class="c1">// 获取所有 partition
</span><span class="c1"></span>	<span class="nx">partitionList</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">subscriber</span><span class="p">.</span><span class="nx">Consumer</span><span class="p">.</span><span class="nf">Partitions</span><span class="p">(</span><span class="nx">topic</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">subscriber</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="nx">error_const</span><span class="p">.</span><span class="nx">SubScriberGetPartitionsError</span><span class="p">,</span> <span class="nx">err</span><span class="p">,</span> <span class="nx">topic</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="c1">// 遍历所有 partition 获取最新 offset 上的消息
</span><span class="c1"></span>	<span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">partition</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">partitionList</span> <span class="p">{</span>
		<span class="nx">pc</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">subscriber</span><span class="p">.</span><span class="nx">Consumer</span><span class="p">.</span><span class="nf">ConsumePartition</span><span class="p">(</span><span class="nx">topic</span><span class="p">,</span> <span class="nx">partition</span><span class="p">,</span> <span class="nx">sarama</span><span class="p">.</span><span class="nx">OffsetNewest</span><span class="p">)</span>
  	<span class="c1">// 启动一个 goroutine 用于持续监听消息
</span><span class="c1"></span>		<span class="k">go</span> <span class="kd">func</span><span class="p">(</span><span class="nx">pc</span> <span class="nx">sarama</span><span class="p">.</span><span class="nx">PartitionConsumer</span><span class="p">)</span> <span class="p">{</span>
			<span class="k">for</span> <span class="nx">message</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">pc</span><span class="p">.</span><span class="nf">Messages</span><span class="p">()</span> <span class="p">{</span>
				<span class="nx">subscriber</span><span class="p">.</span><span class="nx">logger</span><span class="p">.</span><span class="nf">Infof</span><span class="p">(</span><span class="nf">messageReceived</span><span class="p">(</span><span class="nx">message</span><span class="p">))</span>
				<span class="nx">ch</span> <span class="o">&lt;-</span> <span class="nf">messageReceived</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span>
			<span class="p">}</span>
		<span class="p">}(</span><span class="nx">pc</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">messageReceived</span><span class="p">(</span><span class="nx">message</span> <span class="o">*</span><span class="nx">sarama</span><span class="p">.</span><span class="nx">ConsumerMessage</span><span class="p">)</span> <span class="kt">string</span> <span class="p">{</span>
	<span class="k">return</span> <span class="nb">string</span><span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">Value</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="main">main</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
	<span class="s">&#34;os&#34;</span>

	<span class="s">&#34;github.com/sirupsen/logrus&#34;</span>

	<span class="s">&#34;./reporter&#34;</span>
	<span class="s">&#34;./subscriber&#34;</span>
<span class="p">)</span>

<span class="kd">var</span> <span class="p">(</span>
	<span class="nx">config</span> <span class="p">=</span> <span class="s">`{
</span><span class="s">	&#34;host&#34;: &#34;localhost:9092&#34;,
</span><span class="s">	&#34;topic&#34;: &#34;kafka_test&#34;
</span><span class="s">  }`</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="kd">var</span> <span class="nx">cfg</span> <span class="nx">reporter</span><span class="p">.</span><span class="nx">KafkaCfg</span>
	<span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="nx">config</span><span class="p">),</span> <span class="o">&amp;</span><span class="nx">cfg</span><span class="p">)</span>
	<span class="nx">log</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">logrus</span><span class="p">.</span><span class="nx">Logger</span><span class="p">{</span><span class="nx">Out</span><span class="p">:</span> <span class="nx">os</span><span class="p">.</span><span class="nx">Stdout</span><span class="p">}</span>

	<span class="c1">//reporter
</span><span class="c1"></span>	<span class="nx">producer</span> <span class="o">:=</span> <span class="nx">reporter</span><span class="p">.</span><span class="nf">NewReporter</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">cfg</span><span class="p">,</span> <span class="nx">log</span><span class="p">)</span>
	<span class="c1">//subscriber
</span><span class="c1"></span>	<span class="nx">consumer</span> <span class="o">:=</span> <span class="nx">subscriber</span><span class="p">.</span><span class="nf">NewSubscriber</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">cfg</span><span class="p">,</span> <span class="nx">log</span><span class="p">)</span>
	<span class="nx">message</span> <span class="o">:=</span> <span class="s">&#34;Hello Kafka World.&#34;</span>

	<span class="nx">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">string</span><span class="p">)</span>
	<span class="nx">consumer</span><span class="p">.</span><span class="nf">Consume</span><span class="p">(</span><span class="nx">cfg</span><span class="p">.</span><span class="nx">Topic</span><span class="p">,</span> <span class="nx">ch</span><span class="p">)</span>
	<span class="nx">producer</span><span class="p">.</span><span class="nf">DoReport</span><span class="p">(</span><span class="nx">cfg</span><span class="p">.</span><span class="nx">Topic</span><span class="p">,</span> <span class="p">[]</span><span class="nb">byte</span><span class="p">(</span><span class="nx">message</span><span class="p">))</span>

	<span class="k">select</span> <span class="p">{</span>
	<span class="k">case</span> <span class="nx">msg</span> <span class="o">:=</span> <span class="o">&lt;-</span><span class="nx">ch</span><span class="p">:</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Got msg: &#34;</span><span class="p">,</span> <span class="nx">msg</span><span class="p">)</span>
		<span class="k">break</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="其他">其他</h3>

<p>为避免漏消费消息，可指定 group，Kafka 确保每个 partition 只能同一个 group 中的同一个 consumer 消费，若要重复消费，更换 group。</p>

<p>项目代码：<a href="https://github.com/JJMeg/Kafka-with-golang/" target="_blank">kafka-client-golang</a>，项目结构：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">.
├── README.md
├── error_const
│   └── error_const.go
├── main.go
├── reporter
│   └── report.go
└── subscriber
    └── subscribe.go</code></pre></td></tr></table>
</div>
</div>
<p><center>👏欢迎评论👏</center></p>

<script src="https://utteranc.es/client.js"
        repo="JJMeg/jjmeg.io.comment"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/kafka/">kafka</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--JSON解析</title>
                <link>https://jjmeg.github.io/posts/golang-json/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-json/</guid>
                <pubDate>Wed, 06 May 2020 14:32:31 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「  <a href="https://golang.org/pkg/encoding/json/">json</a> 」</center>
<center>
 提供了 JSON 与 Go 变量之间的序列化与反序列化。
</center></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📚 <a href="#JSON序列化">JSON序列化</a></li>
<li>📚 <a href="#tag及使用技巧">tag及使用技巧</a>

<ul>
<li>📖 <a href="#1-省略空字段-omitempty">1. 省略空字段 omitempty</a></li>
<li>📖 <a href="2-忽略特定字段" target="_blank">2. -忽略特定字段</a></li>
<li>📖 <a href="#3-json字段类型转换">3. json字段类型转换</a></li>
<li>📖 <a href="#4-临时添加新字段">4. 临时添加新字段</a></li>
<li>📖 <a href="#5-多结构体组合成">5. 多结构体组合成</a></li>
<li>📖 <a href="#6-对时间类型的序列化">6. 对时间类型的序列化</a></li>
</ul></li>
</ul>

<p></br></p>

<ul>
<li>📚 <a href="#JSON反序列化">JSON反序列化</a></li>
<li>📚 <a href="#JSON反序列化的常用技巧">JSON反序列化的常用技巧</a>

<ul>
<li>📖 <a href="#拆分成多个结构体">拆分成多个结构体</a></li>
</ul></li>
<li>📚 <a href="#JSON与私有属性">JSON与私有属性</a></li>
</ul>

<hr />

<h3 id="json序列化">JSON序列化</h3>

<blockquote>
<p>func Marshal(v interface{}) ([]byte, error)</p>

<p>func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error)</p>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>    <span class="kt">string</span> <span class="s">`json:&#34;city&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{</span>
		<span class="nx">Name</span><span class="p">:</span>    <span class="s">&#34;Amy&#34;</span><span class="p">,</span>
		<span class="nx">Country</span><span class="p">:</span> <span class="s">&#34;China&#34;</span><span class="p">,</span>
		<span class="nx">City</span><span class="p">:</span>    <span class="s">&#34;Beijing&#34;</span><span class="p">,</span>
	<span class="p">}</span>
	<span class="nx">data1</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">(</span><span class="nx">amy</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">data1</span><span class="p">))</span>
	<span class="nx">data2</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span><span class="nx">amy</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34;    &#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">data2</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>使用 <strong>MarshalIndent()</strong> 可使数据输出的形式美观一些</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span><span class="s2">&#34;name&#34;</span>:<span class="s2">&#34;Amy&#34;</span>,<span class="s2">&#34;country&#34;</span>:<span class="s2">&#34;China&#34;</span>,<span class="s2">&#34;city&#34;</span>:<span class="s2">&#34;Beijing&#34;</span><span class="o">}</span>
<span class="o">{</span>
   <span class="s2">&#34;name&#34;</span>: <span class="s2">&#34;Amy&#34;</span>,
   <span class="s2">&#34;country&#34;</span>: <span class="s2">&#34;China&#34;</span>,
   <span class="s2">&#34;city&#34;</span>: <span class="s2">&#34;Beijing&#34;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="tag及使用技巧">tag及使用技巧</h3>

<h6 id="1-省略空字段-omitempty">1. 省略空字段 <strong>omitempty</strong></h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>    <span class="kt">string</span> <span class="s">`json:&#34;city,omitempty&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{</span>
		<span class="nx">Name</span><span class="p">:</span>    <span class="s">&#34;Amy&#34;</span><span class="p">,</span>
	<span class="p">}</span>
	<span class="nx">data</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span><span class="nx">amy</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34;    &#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>JSON内的 <strong>city</strong> 字段增加 <strong>omitempty</strong> 关键字，初始化对象时未对该字段赋值，在序列化后将不显示；<strong>country</strong> 字段未注明忽略空值，序列化赋了默认0值：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>
    <span class="s2">&#34;name&#34;</span>: <span class="s2">&#34;Amy&#34;</span>,
    <span class="s2">&#34;country&#34;</span>: <span class="s2">&#34;&#34;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="2-忽略特定字段">2. 忽略特定字段 <strong>-</strong></h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>    <span class="kt">string</span> <span class="s">`json:&#34;-&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{</span>
		<span class="nx">Name</span><span class="p">:</span>    <span class="s">&#34;Amy&#34;</span><span class="p">,</span>
		<span class="nx">Country</span><span class="p">:</span> <span class="s">&#34;China&#34;</span><span class="p">,</span>
		<span class="nx">City</span><span class="p">:</span>    <span class="s">&#34;Beijing&#34;</span><span class="p">,</span>
	<span class="p">}</span>
	<span class="nx">data</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span><span class="nx">amy</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34;    &#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>即使字段已经初始化，序列化后的内容也不会包含此字段</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>
    <span class="s2">&#34;name&#34;</span>: <span class="s2">&#34;Amy&#34;</span>,
    <span class="s2">&#34;country&#34;</span>: <span class="s2">&#34;China&#34;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="3-json字段类型转换">3. JSON字段类型转换</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Age</span>     <span class="kt">int</span> <span class="s">`json:&#34;age,string&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{</span>
		<span class="nx">Name</span><span class="p">:</span>    <span class="s">&#34;Amy&#34;</span><span class="p">,</span>
		<span class="nx">Age</span><span class="p">:</span>     <span class="mi">25</span><span class="p">,</span>
	<span class="p">}</span>

	<span class="nx">data</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span><span class="nx">amy</span><span class="p">,</span><span class="s">&#34;&#34;</span><span class="p">,</span><span class="s">&#34;    &#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%s\n\n&#34;</span><span class="p">,</span> <span class="nb">string</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>结构体内的 <strong>Age</strong> 字段为整型，加上 <strong>string</strong> 将本字段的值转化为字符串类型：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>
   <span class="s2">&#34;name&#34;</span>: <span class="s2">&#34;Amy&#34;</span>,
   <span class="s2">&#34;age&#34;</span>: <span class="s2">&#34;25&#34;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="4-临时添加新字段">4. 临时添加新字段</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>    <span class="kt">string</span> <span class="s">`json:&#34;city&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{</span>
		<span class="nx">Name</span><span class="p">:</span>    <span class="s">&#34;Amy&#34;</span><span class="p">,</span>
		<span class="nx">Country</span><span class="p">:</span> <span class="s">&#34;China&#34;</span><span class="p">,</span>
		<span class="nx">City</span><span class="p">:</span>    <span class="s">&#34;Beijing&#34;</span><span class="p">,</span>
	<span class="p">}</span>
	<span class="nx">data</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span>
		<span class="kd">struct</span> <span class="p">{</span>
			<span class="nx">person</span>
			<span class="nx">Gender</span> <span class="kt">string</span> <span class="s">`json:&#34;gender&#34;`</span>
		<span class="p">}{</span>
			<span class="nx">person</span><span class="p">:</span> <span class="nx">amy</span><span class="p">,</span>
			<span class="nx">Gender</span><span class="p">:</span> <span class="s">&#34;female&#34;</span><span class="p">,</span>
		<span class="p">},</span><span class="s">&#34;&#34;</span><span class="p">,</span><span class="s">&#34;    &#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>在序列化时新建一个结构体即可：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>
    <span class="s2">&#34;name&#34;</span>: <span class="s2">&#34;Amy&#34;</span>,
    <span class="s2">&#34;country&#34;</span>: <span class="s2">&#34;China&#34;</span>,
    <span class="s2">&#34;city&#34;</span>: <span class="s2">&#34;Beijing&#34;</span>,
    <span class="s2">&#34;gender&#34;</span>: <span class="s2">&#34;female&#34;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="5-多结构体组合成">5. 多结构体组合成</h6>

<p>从4中得到启发，可将多个结构体的字段组合成一个JSON</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>    <span class="kt">string</span> <span class="s">`json:&#34;city&#34;`</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">occupation</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Company</span>  <span class="kt">string</span> <span class="s">`json:&#34;company&#34;`</span>
	<span class="nx">Position</span> <span class="kt">string</span> <span class="s">`json:&#34;position&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{</span>
		<span class="nx">Name</span><span class="p">:</span>    <span class="s">&#34;Amy&#34;</span><span class="p">,</span>
		<span class="nx">Country</span><span class="p">:</span> <span class="s">&#34;China&#34;</span><span class="p">,</span>
		<span class="nx">City</span><span class="p">:</span>    <span class="s">&#34;Beijing&#34;</span><span class="p">,</span>
	<span class="p">}</span>

	<span class="nx">job</span> <span class="o">:=</span> <span class="nx">occupation</span><span class="p">{</span>
		<span class="nx">Company</span><span class="p">:</span>  <span class="s">&#34;Google&#34;</span><span class="p">,</span>
		<span class="nx">Position</span><span class="p">:</span> <span class="s">&#34;developer&#34;</span><span class="p">,</span>
	<span class="p">}</span>
	<span class="nx">data</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span>
		<span class="kd">struct</span> <span class="p">{</span>
			<span class="nx">person</span>
			<span class="nx">occupation</span>
		<span class="p">}{</span>
			<span class="nx">person</span><span class="p">:</span>     <span class="nx">amy</span><span class="p">,</span>
			<span class="nx">occupation</span><span class="p">:</span> <span class="nx">job</span><span class="p">,</span>
		<span class="p">},</span> <span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34;    &#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>
    <span class="s2">&#34;name&#34;</span>: <span class="s2">&#34;Amy&#34;</span>,
    <span class="s2">&#34;country&#34;</span>: <span class="s2">&#34;China&#34;</span>,
    <span class="s2">&#34;city&#34;</span>: <span class="s2">&#34;Beijing&#34;</span>,
    <span class="s2">&#34;company&#34;</span>: <span class="s2">&#34;Google&#34;</span>,
    <span class="s2">&#34;position&#34;</span>: <span class="s2">&#34;developer&#34;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="6-对时间类型的序列化">6. 对时间类型的序列化</h6>

<p>Go对时间的序列化方式是格式化转化成字符串，并默认使用RFC3339标准 <strong>2006-01-02T15:04:05.999999999Z07:00</strong> 做格式化，时间对象转化为JSON默认使用 <strong>MarshalJSON()</strong> 方法</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">t</span> <span class="nx">Time</span><span class="p">)</span> <span class="nf">MarshalJSON</span><span class="p">()</span> <span class="p">([]</span><span class="kt">byte</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nx">y</span> <span class="o">:=</span> <span class="nx">t</span><span class="p">.</span><span class="nf">Year</span><span class="p">();</span> <span class="nx">y</span> <span class="p">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">y</span> <span class="o">&gt;=</span> <span class="mi">10000</span> <span class="p">{</span>
		<span class="c1">// RFC 3339 is clear that years are 4 digits exactly.
</span><span class="c1"></span>		<span class="c1">// See golang.org/issue/4556#c15 for more discussion.
</span><span class="c1"></span>		<span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">New</span><span class="p">(</span><span class="s">&#34;Time.MarshalJSON: year outside of range [0,9999]&#34;</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="nx">b</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">byte</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="nx">RFC3339Nano</span><span class="p">)</span><span class="o">+</span><span class="mi">2</span><span class="p">)</span>
	<span class="nx">b</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">b</span><span class="p">,</span> <span class="sc">&#39;&#34;&#39;</span><span class="p">)</span>
	<span class="nx">b</span> <span class="p">=</span> <span class="nx">t</span><span class="p">.</span><span class="nf">AppendFormat</span><span class="p">(</span><span class="nx">b</span><span class="p">,</span> <span class="nx">RFC3339Nano</span><span class="p">)</span>
	<span class="nx">b</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">b</span><span class="p">,</span> <span class="sc">&#39;&#34;&#39;</span><span class="p">)</span>
	<span class="k">return</span> <span class="nx">b</span><span class="p">,</span> <span class="kc">nil</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>Marshaler</strong> 接口定义了 <strong>MarshalJSON()</strong> 方法，Go中的时间 <strong>time.Time</strong> 实现了 <strong>Marshaler</strong> 接口:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">Marshaler</span> <span class="kd">interface</span> <span class="p">{</span>
        <span class="nf">MarshalJSON</span><span class="p">()</span> <span class="p">([]</span><span class="kt">byte</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>结合上述思路，我们可以自定义时间类型，实现 <strong>Marshaler</strong> 接口，达到自定义序列化的目的:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
	<span class="s">&#34;time&#34;</span>
<span class="p">)</span>

<span class="c1">//自定义时间类型
</span><span class="c1"></span><span class="kd">type</span> <span class="nx">MyTime</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Time</span>

<span class="c1">// 实现Marshaler接口
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">mytime</span> <span class="nx">MyTime</span><span class="p">)</span> <span class="nf">MarshalJSON</span><span class="p">()</span> <span class="p">([]</span><span class="kt">byte</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="nx">n</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Time</span><span class="p">(</span><span class="nx">mytime</span><span class="p">).</span><span class="nf">Format</span><span class="p">(</span><span class="s">&#34;2006-01-02 15:04&#34;</span><span class="p">)</span>
	<span class="nx">t</span> <span class="o">:=</span> <span class="s">&#34;\&#34;&#34;</span> <span class="o">+</span> <span class="nx">n</span> <span class="o">+</span> <span class="s">&#34;\&#34;&#34;</span>
	<span class="k">return</span> <span class="p">[]</span><span class="nb">byte</span><span class="p">(</span><span class="nx">t</span><span class="p">),</span> <span class="kc">nil</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>     <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span>  <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>     <span class="kt">string</span> <span class="s">`json:&#34;city&#34;`</span>
	<span class="nx">Birthday</span> <span class="nx">MyTime</span> <span class="s">`json:&#34;birthday&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{</span>
		<span class="nx">Name</span><span class="p">:</span>     <span class="s">&#34;Amy&#34;</span><span class="p">,</span>
		<span class="nx">Country</span><span class="p">:</span>  <span class="s">&#34;China&#34;</span><span class="p">,</span>
		<span class="nx">City</span><span class="p">:</span>     <span class="s">&#34;Beijing&#34;</span><span class="p">,</span>
		<span class="nx">Birthday</span><span class="p">:</span> <span class="nf">MyTime</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()),</span>
	<span class="p">}</span>
	<span class="nx">data</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">MarshalIndent</span><span class="p">(</span><span class="nx">amy</span><span class="p">,</span> <span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34;    &#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>本例将时间输出格式修改为 <strong>年-月-日 时:分</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>
    <span class="s2">&#34;name&#34;</span>: <span class="s2">&#34;Amy&#34;</span>,
    <span class="s2">&#34;country&#34;</span>: <span class="s2">&#34;China&#34;</span>,
    <span class="s2">&#34;city&#34;</span>: <span class="s2">&#34;Beijing&#34;</span>,
    <span class="s2">&#34;birthday&#34;</span>: <span class="s2">&#34;2019-09-05 18:42&#34;</span>
<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<hr />

<h3 id="json反序列化">JSON反序列化</h3>

<blockquote>
<p>func Unmarshal(data []byte, v interface{}) error</p>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>    <span class="kt">string</span> <span class="s">`json:&#34;city&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">data</span> <span class="o">:=</span> <span class="s">`{
</span><span class="s">	&#34;name&#34;: &#34;Amy&#34;,
</span><span class="s">	&#34;country&#34;: &#34;China&#34;,
</span><span class="s">	&#34;city&#34;:&#34;Beijing&#34;
</span><span class="s">	}`</span>
	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{}</span>
	<span class="nx">err</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="nx">data</span><span class="p">),</span> <span class="o">&amp;</span><span class="nx">amy</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%s\n%s\n%s\n&#34;</span><span class="p">,</span> <span class="nx">amy</span><span class="p">.</span><span class="nx">Name</span><span class="p">,</span> <span class="nx">amy</span><span class="p">.</span><span class="nx">Country</span><span class="p">,</span> <span class="nx">amy</span><span class="p">.</span><span class="nx">City</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>反序列化完成字符串到对象的转化，当 <strong>Unmarshal()</strong> 方法返回错误不空表示反序列化失败</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Amy
China
Beijing</code></pre></td></tr></table>
</div>
</div>
<h3 id="json反序列化的常用技巧">JSON反序列化的常用技巧</h3>

<h6 id="拆分成多个结构体">拆分成多个结构体</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">Country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
	<span class="nx">City</span>    <span class="kt">string</span> <span class="s">`json:&#34;city&#34;`</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">occupation</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Company</span>  <span class="kt">string</span> <span class="s">`json:&#34;company&#34;`</span>
	<span class="nx">Position</span> <span class="kt">string</span> <span class="s">`json:&#34;position&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">data</span> <span class="o">:=</span> <span class="s">`{
</span><span class="s">	&#34;name&#34;: &#34;Amy&#34;,
</span><span class="s">	&#34;country&#34;: &#34;China&#34;,
</span><span class="s">	&#34;city&#34;:&#34;Beijing&#34;,
</span><span class="s">	&#34;company&#34;:&#34;Google&#34;,
</span><span class="s">	&#34;position&#34;:&#34;developer&#34;
</span><span class="s">	}`</span>

	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">person</span><span class="p">{}</span>
	<span class="nx">job</span> <span class="o">:=</span> <span class="nx">occupation</span><span class="p">{}</span>

	<span class="nx">err</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="nx">data</span><span class="p">),</span>
		<span class="o">&amp;</span><span class="kd">struct</span> <span class="p">{</span>
			<span class="o">*</span><span class="nx">person</span>
			<span class="o">*</span><span class="nx">occupation</span>
		<span class="p">}{</span><span class="o">&amp;</span><span class="nx">amy</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">job</span><span class="p">})</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%v\n%v\n&#34;</span><span class="p">,</span> <span class="nx">amy</span><span class="p">,</span> <span class="nx">job</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>Amy China Beijing<span class="o">}</span>
<span class="o">{</span>Google developer<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<hr />

<h3 id="json与私有属性">JSON与私有属性</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
	<span class="s">&#34;encoding/json&#34;</span>
	<span class="s">&#34;fmt&#34;</span>
<span class="p">)</span>

<span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>    <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
	<span class="nx">country</span> <span class="kt">string</span> <span class="s">`json:&#34;country&#34;`</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">d</span> <span class="o">:=</span> <span class="s">`{
</span><span class="s">	&#34;name&#34;: &#34;Amy&#34;,
</span><span class="s">	&#34;country&#34;: &#34;China&#34;
</span><span class="s">	}`</span>

	<span class="nx">amy</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{}</span>

	<span class="nx">err</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="nx">d</span><span class="p">),</span><span class="o">&amp;</span><span class="nx">amy</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%v\n&#34;</span><span class="p">,</span> <span class="nx">amy</span><span class="p">)</span>
	<span class="p">}</span>

  <span class="nx">Sam</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span>
    <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;Sam&#34;</span><span class="p">,</span>
    <span class="nx">country</span><span class="p">:</span> <span class="s">&#34;CN&#34;</span><span class="p">,</span>
  <span class="p">}</span>
  <span class="nx">data</span><span class="p">,</span><span class="nx">err</span> <span class="o">:=</span> <span class="nx">json</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">(</span><span class="nx">Sam</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%v\n&#34;</span><span class="p">,</span> <span class="nb">string</span><span class="p">(</span><span class="nx">data</span><span class="p">))</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><code>Person</code> 内的 <code>country</code> 是私有属性，JSON的序列化及反序列化都不会对私有属性转化。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span>Amy<span class="o">}</span>
<span class="o">{</span><span class="s2">&#34;name&#34;</span>:<span class="s2">&#34;Sam&#34;</span><span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<p><center>👏欢迎评论👏</center></p>

<script src="https://utteranc.es/client.js"
        repo="JJMeg/jjmeg.io.comment"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Go实现一个支持动态扩容的数组</title>
                <link>https://jjmeg.github.io/posts/buffered-array/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/buffered-array/</guid>
                <pubDate>Tue, 21 Jan 2020 16:14:25 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「 数组 」</center>
<center>一旦分配空间，不可再更改，容量限定，可能存在访问越界风险。</center></p>

<hr />

<p>在此实现支持动态扩容的数组，能完成基本的增删改查操作，其数据结构定义及构造函数如下，使用数组 <code>Data</code> 保存数据，用 <code>Size</code> 记录当前已保存的数据的个数：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">MyArray</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Data</span> <span class="p">[]</span><span class="kd">interface</span><span class="p">{}</span>
	<span class="nx">Size</span> <span class="kt">int</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">NewMyArray</span><span class="p">(</span><span class="nx">size</span> <span class="kt">int</span><span class="p">)</span> <span class="o">*</span><span class="nx">MyArray</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nx">size</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
		<span class="k">return</span> <span class="kc">nil</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="o">&amp;</span><span class="nx">MyArray</span><span class="p">{</span>
		<span class="nb">make</span><span class="p">([]</span><span class="kd">interface</span><span class="p">{},</span> <span class="nx">size</span><span class="p">),</span>
		<span class="nx">size</span><span class="p">,</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="快速访问">📜快速访问</h3>

<ul>
<li>📚<a href="#增">增</a></li>
<li>📚<a href="#删">删</a></li>
<li>📚<a href="#改">改</a></li>
<li>📚<a href="#查">查</a></li>
<li>📚<a href="#其他">其他</a></li>
</ul>

<h3 id="增">增</h3>

<p><code>MyArray</code> 内的 <code>Data</code> 本质是一个数组，在插入数据时，要考虑 <code>Data</code> 是否还有多余的空间保存数据，当空间不够时，我们对其进行扩容。扩容时，将容量翻倍，即申请一段新的连续内存，将已有的数据保存到新的内存空间中，时间复杂度为 O(n):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">resize</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">newArray</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kd">interface</span><span class="p">{},</span> <span class="mi">2</span><span class="o">*</span><span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="p">)</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;=</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
		<span class="nx">newArray</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="p">=</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
	<span class="p">}</span>
	<span class="nx">m</span><span class="p">.</span><span class="nx">Data</span> <span class="p">=</span> <span class="nx">newArray</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><code>Data</code> 的最大容量为 <code>len(Data)</code> ，添加单个或多个数据时，比对 <code>Size</code> 和最大容量得知是否要扩容：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">AddItem</span><span class="p">(</span><span class="nx">item</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">)</span> <span class="o">==</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span> <span class="p">{</span>
		<span class="nx">m</span><span class="p">.</span><span class="nf">resize</span><span class="p">()</span>
	<span class="p">}</span>
	<span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="p">]</span> <span class="p">=</span> <span class="nx">item</span>
	<span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="o">++</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">AddItems</span><span class="p">(</span><span class="nx">items</span> <span class="o">...</span><span class="kd">interface</span><span class="p">{})</span> <span class="p">{</span>
	<span class="k">for</span> <span class="nx">item</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">items</span> <span class="p">{</span>
		<span class="nx">m</span><span class="p">.</span><span class="nf">AddItem</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="删">删</h3>

<p>删除操作有两种方式，删除具体数据，可能存在多个相同的数据，</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 删
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">Remove</span><span class="p">(</span><span class="nx">target</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">{</span>
	<span class="nx">newArray</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kd">interface</span><span class="p">{},</span> <span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">))</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
		<span class="k">if</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">!=</span> <span class="nx">target</span> <span class="p">{</span>
			<span class="nx">newArray</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">newArray</span><span class="p">,</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span>
		<span class="p">}</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>以及删除数组指定下标的数据，在删除前，要检查下标是否合法：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">RemoveWithIndex</span><span class="p">(</span><span class="nx">index</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nx">index</span> <span class="p">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">index</span> <span class="p">&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">)</span> <span class="p">{</span>
		<span class="nb">panic</span><span class="p">(</span><span class="s">&#34;Illegal index.&#34;</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">newArray</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kd">interface</span><span class="p">{},</span> <span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">))</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
		<span class="k">if</span> <span class="nx">i</span> <span class="o">!=</span> <span class="nx">index</span> <span class="p">{</span>
			<span class="nx">newArray</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="p">=</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
		<span class="p">}</span>
	<span class="p">}</span>
	<span class="nx">m</span><span class="p">.</span><span class="nx">Data</span> <span class="p">=</span> <span class="nx">newArray</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="改">改</h3>

<p>修改一般是对指定下标的数据做修改，类似删除，也需要做下标合法检查：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">Set</span><span class="p">(</span><span class="nx">index</span> <span class="kt">int</span><span class="p">,</span> <span class="nx">item</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nx">index</span> <span class="p">&lt;</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">index</span> <span class="p">&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">)</span> <span class="p">{</span>
		<span class="nb">panic</span><span class="p">(</span><span class="s">&#34;Illegal index.&#34;</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span> <span class="p">=</span> <span class="nx">item</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="查">查</h3>

<p>查找支持查找单个和查找多个，根据数据内容查找对应的数组下标，并利用这个方法判断数据是否存在于数组中：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">FindItem</span><span class="p">(</span><span class="nx">target</span> <span class="kd">interface</span><span class="p">{})</span> <span class="kt">int</span> <span class="p">{</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
		<span class="k">if</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">==</span> <span class="nx">target</span> <span class="p">{</span>
			<span class="k">return</span> <span class="nx">i</span>
		<span class="p">}</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="o">-</span><span class="mi">1</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">FindAllItems</span><span class="p">(</span><span class="nx">target</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">(</span><span class="nx">result</span> <span class="p">[]</span><span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span> <span class="p">{</span>
		<span class="k">if</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">==</span> <span class="nx">target</span> <span class="p">{</span>
			<span class="nx">result</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">result</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>
	<span class="k">return</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">Contains</span><span class="p">(</span><span class="nx">target</span> <span class="kd">interface</span><span class="p">{})</span> <span class="kt">bool</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nx">m</span><span class="p">.</span><span class="nf">FindItem</span><span class="p">(</span><span class="nx">target</span><span class="p">)</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span> <span class="p">{</span>
		<span class="k">return</span> <span class="kc">false</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="kc">true</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>根据数组下标查找具体的数据，批量查找应以列表的形式返回：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">GetItem</span><span class="p">(</span><span class="nx">index</span> <span class="kt">int</span><span class="p">)</span> <span class="kd">interface</span><span class="p">{}</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nx">index</span> <span class="p">&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">)</span> <span class="o">||</span> <span class="nx">index</span> <span class="p">&lt;</span> <span class="mi">0</span> <span class="p">{</span>
		<span class="k">return</span> <span class="kc">nil</span>
	<span class="p">}</span>
	<span class="k">return</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">GetItems</span><span class="p">(</span><span class="nx">indexes</span> <span class="o">...</span><span class="kt">int</span><span class="p">)</span> <span class="p">[]</span><span class="kd">interface</span><span class="p">{}</span> <span class="p">{</span>
	<span class="nx">result</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kd">interface</span><span class="p">{},</span> <span class="nb">len</span><span class="p">(</span><span class="nx">indexes</span><span class="p">))</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">indexes</span> <span class="p">{</span>
		<span class="k">if</span> <span class="nx">i</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="nx">i</span> <span class="p">&lt;</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span> <span class="p">{</span>
			<span class="nx">result</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">result</span><span class="p">,</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="nx">result</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="其他">其他</h3>

<p>获取最大容量及当前容量，使用当前容量判断数组是否为空：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">GetCapacity</span><span class="p">()</span> <span class="kt">int</span> <span class="p">{</span>
	<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">Data</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">GetSize</span><span class="p">()</span> <span class="kt">int</span> <span class="p">{</span>
	<span class="k">return</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">m</span> <span class="o">*</span><span class="nx">MyArray</span><span class="p">)</span> <span class="nf">IsEmpty</span><span class="p">()</span> <span class="kt">bool</span> <span class="p">{</span>
	<span class="k">return</span> <span class="nx">m</span><span class="p">.</span><span class="nx">Size</span> <span class="o">==</span> <span class="mi">0</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<script src="https://utteranc.es/client.js"
        repo="JJMeg/jjmeg.io.comment"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E6%95%B0%E7%BB%84/">数组</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/">数据结构</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang源码阅读 - channel 和 select（一）</title>
                <link>https://jjmeg.github.io/posts/golang-channel-and-select/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-channel-and-select/</guid>
                <pubDate>Tue, 14 Jan 2020 11:25:07 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「 channel 和 select 」</center>
<center>Go 提供 channel 模型实现同步。</center></p>

<p style="text-indent:2em">实现同步的两个思路：共享内存、消息通信（内存拷贝），共享内存通常通过锁机制实现，消息通信则基于 [CSP理论](http://www.usingcsp.com/cspbook.pdf)。</p>

<p style="text-indent:2em">go 显示使用 channel ，需要程序员显示的分配消息通道，channel 分为无缓冲的和缓冲两种类型。在了解 channel 内部实现之前，我们先了解 go 语言的调度模型。</p>

<p>go 的调度模型 GPM 模型：</p>

<ul>
<li>G - goroutine，Global 队列存放 G</li>
<li>P - processer，逻辑处理器，P 的 local 队列也存放 G</li>
<li>M - machine，实际运行 golang 程序作业</li>
</ul>

<p><p style="text-indent:2em">M 实际运行要绑定一个 P ，P 类似一个存放资源的队列，P 的 local 队列内存放 G 。M 与 P 绑定，不断从 P 的 local 队列内取 G(无锁操作)，切换到 G 的堆栈执行，若没有了 G，则从 Global 队列内取 G (有锁操作)，可能会取一批到 P 的 local 队列内，若 Global 内也没有 G ，则尝试从其他 P 中窃取 G ，一般窃取一半，当没有 G 时， M 和 P 解绑，进入休眠。</p>
<img src="/images/channel-select/go-scheduler.png" alt="go-scheduler.png" /></p>

<h3 id="channel数据结构">channel数据结构</h3>

<p><code>src/runtime/chan.go</code></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">hchan</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">qcount</span>   <span class="kt">uint</span>           <span class="c1">// 队列中的数据的量
</span><span class="c1"></span>	<span class="nx">dataqsiz</span> <span class="kt">uint</span>           <span class="c1">// 环形队列的大小
</span><span class="c1"></span>	<span class="nx">buf</span>      <span class="nx">unsafe</span><span class="p">.</span><span class="nx">Pointer</span> <span class="c1">// 指向 dataqsiz 大小的的数组
</span><span class="c1"></span>	<span class="nx">elemsize</span> <span class="kt">uint16</span> <span class="c1">// 元素大小
</span><span class="c1"></span>	<span class="nx">closed</span>   <span class="kt">uint32</span> <span class="c1">// 是否关闭
</span><span class="c1"></span>	<span class="nx">elemtype</span> <span class="o">*</span><span class="nx">_type</span> <span class="c1">// 元素类型
</span><span class="c1"></span>	<span class="nx">sendx</span>    <span class="kt">uint</span>   <span class="c1">// 发送索引
</span><span class="c1"></span>	<span class="nx">recvx</span>    <span class="kt">uint</span>   <span class="c1">// 接收索引
</span><span class="c1"></span>	<span class="nx">recvq</span>    <span class="nx">waitq</span>  <span class="c1">// 接收列表即 &lt;-chan
</span><span class="c1"></span>	<span class="nx">sendq</span>    <span class="nx">waitq</span>  <span class="c1">// 发送列表即 ch&lt;-
</span><span class="c1"></span>
	<span class="nx">lock</span> <span class="nx">mutex</span>
	<span class="c1">// lock保护 hchan 结构体内的所有字段，以及 waitq 内的 sudog，
</span><span class="c1"></span>	<span class="c1">// 在持有该锁时，不要改变 G 的状态，因为在栈收缩时会死锁
</span><span class="c1"></span><span class="p">}</span>


<span class="kd">type</span> <span class="nx">waitq</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">first</span> <span class="o">*</span><span class="nx">sudog</span>
	<span class="nx">last</span>  <span class="o">*</span><span class="nx">sudog</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><code>waitq</code> 是等待队列和发送队列的包装，包装了当前 goroutine 的指针，即 <code>waitq</code> 指向了一个 goroutine 指针队列，是一个双向队列。初始化带缓冲的 hchan 时：
<img src="/images/channel-select/channel-select-new.png" alt="channel-select-new.png" />
如上图，初始化一个有 4 个缓冲区的通道，<code>buf</code> 指向一个有界数组，<code>sendx</code> 表示下一次发送数据时要访问 <code>buf</code> 数组的下标，<code>recvx</code> 则表示下一次接收数据时要访问的下标，<code>recvq</code> 保存待接收通道数据的 goroutine 链表，类似的，<code>sendq</code> 负责保存发送数据的 goroutine 。</p>

<p>以此 channel 为例，带有 4 个缓冲区，首先看看 channel 接收数据的流程。</p>

<h5 id="channel接收数据流程">channel接收数据流程</h5>

<p>① 协程 G 预往 channel 中插入数据 4，此时 <code>sendx</code> 为 0，表示若要插入数据，将数据放在 <code>buf</code> 下标为 0 处，缓冲区 <code>buf</code> 内空间未满，直接将 G 的数据插入到 <code>buf</code> 内，G 携带的数据放在 <code>buf[0]</code> 处， <code>sendx</code> 加一：
<img src="/images/channel-select/channel-select-G1.png" alt="channel-select-G1.png" /></p>

<p>② 第二个协程 G2 携带数据，与第 ① 步类似，<code>buf</code> 空间未满，直接插入，<code>sendx</code> 索引加一：
<img src="/images/channel-select/channel-select-G2.png" alt="channel-select-G2.png" /></p>

<p>③ 当插入数据到 <code>buf</code> ，<code>buf</code>空间恰好满了，此时 <code>sendx</code> 归为 0，如此设计让 channel 的缓冲区成为一个 FIFO 类型的通道：
<img src="/images/channel-select/channel-select-G4.png" alt="channel-select-G4.png" /></p>

<p>④ 协程 G5 要插入数据，但是 <code>buf</code> 空间已满，则将 G5 插入到发送数据等待队列 <code>sendq</code>，即被阻塞，直到 <code>buf</code> 有空间才从 <code>sendq</code> 取出 G 插入数据:
<img src="/images/channel-select/channel-select-G5.png" alt="channel-select-G5.png" /></p>

<h5 id="channel发送数据流程">channel发送数据流程</h5>

<p>① 协程 G 预接收数据，<code>recvx</code> 表示 channel 下一个要发送的数据的下标，<code>buf</code> 内有数据，channel 直接将数据发送给 G ,<code>recvx</code> 加一：
<img src="/images/channel-select/channel-select-send-G.png" alt="channel-select-send-G.png" /></p>

<p>② 协程 G2 预接收数据，channel 最后一个数据发送给 G2 ， <code>buf</code> 为空，<code>recvx</code> 应归 0：
<img src="/images/channel-select/channel-select-send-G2.png" alt="channel-select-send-G2.png" /></p>

<p>③ 协程 G3 也要接收 channel 的数据，但是 <code>buf</code> 内已无数据，G3 则被挂起，被放入 <code>recvq</code> 队列内排队：
<img src="/images/channel-select/channel-select-send-G3.png" alt="channel-select-send-G3.png" /></p>

<h5 id="总结">总结</h5>

<p>channel 接收数据时要考虑 <code>buf</code> 是否已满，影响的是 <code>sendx</code> 和 <code>sendq</code> 两个属性，缓冲区满时，协程入 <code>sendq</code> 队列；类似的， channel 发送数据时要考虑 <code>buf</code> 内没有数据的情况，影响 <code>recvx</code> 和 <code>recvq</code> 两个属性。<code>sendx</code> 及 <code>recvx</code> 的变化规律表明 channel 存取数据的方式是先入先出 FIFO 的形式。</p>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/">源码阅读</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>cache2go源码阅读（二）</title>
                <link>https://jjmeg.github.io/posts/cache2go_ii/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/cache2go_ii/</guid>
                <pubDate>Thu, 02 Jan 2020 15:54:51 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<h3 id="缓存表的排序">缓存表的排序</h3>

<p>为了实现获取缓存表内最多访问的元素，引入这两个数据结构用于排序：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">CacheItemPair</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Key</span>         <span class="kd">interface</span><span class="p">{}</span>
	<span class="nx">AccessCount</span> <span class="kt">int64</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">CacheItemPairList</span> <span class="p">[]</span><span class="nx">CacheItemPair</span></code></pre></td></tr></table>
</div>
</div>
<p><code>CacheItemPairList</code>是存储<code>CacheItemPair</code>的切片，有以下三个方法</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">p</span> <span class="nx">CacheItemPairList</span><span class="p">)</span> <span class="nf">Swap</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span>      <span class="p">{</span> <span class="nx">p</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">p</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p">=</span> <span class="nx">p</span><span class="p">[</span><span class="nx">j</span><span class="p">],</span> <span class="nx">p</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="p">}</span>
<span class="kd">func</span> <span class="p">(</span><span class="nx">p</span> <span class="nx">CacheItemPairList</span><span class="p">)</span> <span class="nf">Len</span><span class="p">()</span> <span class="kt">int</span>           <span class="p">{</span> <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="nx">p</span><span class="p">)</span> <span class="p">}</span>
<span class="kd">func</span> <span class="p">(</span><span class="nx">p</span> <span class="nx">CacheItemPairList</span><span class="p">)</span> <span class="nf">Less</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">p</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">AccessCount</span> <span class="p">&gt;</span> <span class="nx">p</span><span class="p">[</span><span class="nx">j</span><span class="p">].</span><span class="nx">AccessCount</span> <span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>为什么是这三个方法，进入<code>sort</code>包，包实现的排序都是对<code>Interface</code>这个接口做的，因此被排序的数据结构需要实现这三个方法</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">Interface</span> <span class="kd">interface</span> <span class="p">{</span>
	<span class="c1">// Len is the number of elements in the collection.
</span><span class="c1"></span>	<span class="nf">Len</span><span class="p">()</span> <span class="kt">int</span>
	<span class="c1">// Less reports whether the element with
</span><span class="c1"></span>	<span class="c1">// index i should sort before the element with index j.
</span><span class="c1"></span>	<span class="nf">Less</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span>
	<span class="c1">// Swap swaps the elements with indexes i and j.
</span><span class="c1"></span>	<span class="nf">Swap</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>借助<code>CacheItemPair</code>，存储<code>key</code>和访问次数<code>accessCount</code>，通过<code>CacheItemPairList</code>实现排序，排序完的列表，再遍历得到元素，构造新顺序的元素表</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">MostAccessed</span><span class="p">(</span><span class="nx">count</span> <span class="kt">int64</span><span class="p">)</span> <span class="p">[]</span><span class="o">*</span><span class="nx">CacheItem</span> <span class="p">{</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">table</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span>

	<span class="nx">p</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="nx">CacheItemPairList</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="nx">table</span><span class="p">.</span><span class="nx">items</span><span class="p">))</span>
	<span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span>
	<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">table</span><span class="p">.</span><span class="nx">items</span> <span class="p">{</span>
		<span class="nx">p</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="p">=</span> <span class="nx">CacheItemPair</span><span class="p">{</span><span class="nx">k</span><span class="p">,</span> <span class="nx">v</span><span class="p">.</span><span class="nx">accessCount</span><span class="p">}</span>
		<span class="nx">i</span><span class="o">++</span>
	<span class="p">}</span>
	<span class="nx">sort</span><span class="p">.</span><span class="nf">Sort</span><span class="p">(</span><span class="nx">p</span><span class="p">)</span>

	<span class="kd">var</span> <span class="nx">r</span> <span class="p">[]</span><span class="o">*</span><span class="nx">CacheItem</span>
	<span class="nx">c</span> <span class="o">:=</span> <span class="nb">int64</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
	<span class="c1">// p经过排序后，通过遍历构造新的items list
</span><span class="c1"></span>	<span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">p</span> <span class="p">{</span>
		<span class="k">if</span> <span class="nx">c</span> <span class="o">&gt;=</span> <span class="nx">count</span> <span class="p">{</span>
			<span class="k">break</span>
		<span class="p">}</span>

		<span class="nx">item</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">table</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="nx">v</span><span class="p">.</span><span class="nx">Key</span><span class="p">]</span>
		<span class="k">if</span> <span class="nx">ok</span> <span class="p">{</span>
			<span class="nx">r</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">r</span><span class="p">,</span> <span class="nx">item</span><span class="p">)</span>
		<span class="p">}</span>
		<span class="nx">c</span><span class="o">++</span>
	<span class="p">}</span>

	<span class="k">return</span> <span class="nx">r</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/">源码阅读</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/cache2go/">cache2go</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>cache2go源码阅读（一）</title>
                <link>https://jjmeg.github.io/posts/cache2go_i/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/cache2go_i/</guid>
                <pubDate>Thu, 02 Jan 2020 15:17:51 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「 <a href="https://github.com/muesli/cache2go" target="_blank">cache2go</a> 」</center>
<center>并发安全的golang缓存库，支持过期功能。</center></p>

<h3 id="从example开始">从Example开始</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 待存储的元素的结构体定义
</span><span class="c1"></span><span class="kd">type</span> <span class="nx">myStruct</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">text</span>     <span class="kt">string</span>
	<span class="nx">moreData</span> <span class="p">[]</span><span class="kt">byte</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="c1">// 创建一个缓存表
</span><span class="c1"></span>	<span class="nx">cache</span> <span class="o">:=</span> <span class="nx">cache2go</span><span class="p">.</span><span class="nf">Cache</span><span class="p">(</span><span class="s">&#34;myCache&#34;</span><span class="p">)</span>

  <span class="c1">// 准备元素
</span><span class="c1"></span>	<span class="nx">val</span> <span class="o">:=</span> <span class="nx">myStruct</span><span class="p">{</span><span class="s">&#34;This is a test!&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">{}}</span>

  <span class="c1">// 缓存表添加元素，设定过期时间
</span><span class="c1"></span>	<span class="nx">cache</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="s">&#34;someKey&#34;</span><span class="p">,</span> <span class="mi">5</span><span class="o">*</span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">val</span><span class="p">)</span>

	<span class="c1">// 从缓存中获取元素
</span><span class="c1"></span>	<span class="nx">res</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">cache</span><span class="p">.</span><span class="nf">Value</span><span class="p">(</span><span class="s">&#34;someKey&#34;</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">==</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Found value in cache:&#34;</span><span class="p">,</span> <span class="nx">res</span><span class="p">.</span><span class="nf">Data</span><span class="p">().(</span><span class="o">*</span><span class="nx">myStruct</span><span class="p">).</span><span class="nx">text</span><span class="p">)</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Error retrieving value from cache:&#34;</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="c1">// 等待直至元素过期
</span><span class="c1"></span>	<span class="nx">time</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="mi">6</span> <span class="o">*</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span>
	<span class="nx">res</span><span class="p">,</span> <span class="nx">err</span> <span class="p">=</span> <span class="nx">cache</span><span class="p">.</span><span class="nf">Value</span><span class="p">(</span><span class="s">&#34;someKey&#34;</span><span class="p">)</span>
	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Item is not cached (anymore).&#34;</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="c1">// 添加新的永不过期的元素
</span><span class="c1"></span>	<span class="nx">cache</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="s">&#34;someKey&#34;</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">val</span><span class="p">)</span>

	<span class="c1">// 设置删除元素时给反馈
</span><span class="c1"></span>	<span class="nx">cache</span><span class="p">.</span><span class="nf">SetAboutToDeleteItemCallback</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">e</span> <span class="o">*</span><span class="nx">cache2go</span><span class="p">.</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Deleting:&#34;</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Key</span><span class="p">(),</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Data</span><span class="p">().(</span><span class="o">*</span><span class="nx">myStruct</span><span class="p">).</span><span class="nx">text</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">CreatedOn</span><span class="p">())</span>
	<span class="p">})</span>

	<span class="c1">// 移除元素
</span><span class="c1"></span>	<span class="nx">cache</span><span class="p">.</span><span class="nf">Delete</span><span class="p">(</span><span class="s">&#34;someKey&#34;</span><span class="p">)</span>

	<span class="c1">// 清空缓存
</span><span class="c1"></span>	<span class="nx">cache</span><span class="p">.</span><span class="nf">Flush</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>这个example完成了以下事情：</p>

<ul>
<li>新建缓存表</li>
<li>往表内添加、删除元素</li>
<li>元素过期处理</li>
</ul>

<p>从这个例子来看，能发现两个重要的数据结构，缓存表<code>CacheTable</code>，和元素<code>CacheItem</code>。</p>

<h3 id="主要数据结构-cachetable和cacheitem">主要数据结构：CacheTable和CacheItem</h3>

<h6 id="1-元素cacheitem">1. 元素CacheItem</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">CacheItem</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">sync</span><span class="p">.</span><span class="nx">RWMutex</span>

	<span class="c1">// 元素的key
</span><span class="c1"></span>	<span class="nx">key</span> <span class="kd">interface</span><span class="p">{}</span>
	<span class="c1">// 元素内容
</span><span class="c1"></span>	<span class="nx">data</span> <span class="kd">interface</span><span class="p">{}</span>
	<span class="c1">// 元素生命周期
</span><span class="c1"></span>	<span class="nx">lifeSpan</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Duration</span>

	<span class="c1">// 创建时间
</span><span class="c1"></span>	<span class="nx">createdOn</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Time</span>
	<span class="c1">// 最后被访问时间
</span><span class="c1"></span>	<span class="nx">accessedOn</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Time</span>
	<span class="c1">// 访问次数
</span><span class="c1"></span>	<span class="nx">accessCount</span> <span class="kt">int64</span>

	<span class="c1">// 到期签可触发的方法
</span><span class="c1"></span>	<span class="nx">aboutToExpire</span> <span class="p">[]</span><span class="kd">func</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{})</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>构造函数</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-go" data-lang="go"><span class="kd">func</span> <span class="nf">NewCacheItem</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">lifeSpan</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Duration</span><span class="p">,</span> <span class="nx">data</span> <span class="kd">interface</span><span class="p">{})</span> <span class="o">*</span><span class="nx">CacheItem</span> <span class="p">{</span>
	<span class="nx">t</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span>
	<span class="k">return</span> <span class="o">&amp;</span><span class="nx">CacheItem</span><span class="p">{</span>
		<span class="nx">key</span><span class="p">:</span>           <span class="nx">key</span><span class="p">,</span>
		<span class="nx">lifeSpan</span><span class="p">:</span>      <span class="nx">lifeSpan</span><span class="p">,</span>
		<span class="nx">createdOn</span><span class="p">:</span>     <span class="nx">t</span><span class="p">,</span>
		<span class="nx">accessedOn</span><span class="p">:</span>    <span class="nx">t</span><span class="p">,</span>
		<span class="nx">accessCount</span><span class="p">:</span>   <span class="mi">0</span><span class="p">,</span>
		<span class="nx">aboutToExpire</span><span class="p">:</span> <span class="kc">nil</span><span class="p">,</span>
		<span class="nx">data</span><span class="p">:</span>          <span class="nx">data</span><span class="p">,</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>cache2go是并发安全的，CacheItem内有个读写锁，在对可能被其他线程改写的属性进行访问时，都会做上锁操作，通过这个锁实现cache2go的并发安全。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="nf">KeepAlive</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">item</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">item</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>
	<span class="nx">item</span><span class="p">.</span><span class="nx">accessedOn</span> <span class="p">=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span>
	<span class="nx">item</span><span class="p">.</span><span class="nx">accessCount</span><span class="o">++</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="nf">AccessedOn</span><span class="p">()</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Time</span> <span class="p">{</span>
	<span class="nx">item</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">item</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span>
	<span class="k">return</span> <span class="nx">item</span><span class="p">.</span><span class="nx">accessedOn</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="nf">AccessCount</span><span class="p">()</span> <span class="kt">int64</span> <span class="p">{</span>
	<span class="nx">item</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">item</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span>
	<span class="k">return</span> <span class="nx">item</span><span class="p">.</span><span class="nx">accessCount</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="nf">SetAboutToExpireCallback</span><span class="p">(</span><span class="nx">f</span> <span class="kd">func</span><span class="p">(</span><span class="kd">interface</span><span class="p">{}))</span> <span class="p">{</span>
	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">aboutToExpire</span><span class="p">)</span> <span class="p">&gt;</span> <span class="mi">0</span> <span class="p">{</span>
		<span class="nx">item</span><span class="p">.</span><span class="nf">RemoveAboutToExpireCallback</span><span class="p">()</span>
	<span class="p">}</span>
	<span class="nx">item</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">item</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>
	<span class="nx">item</span><span class="p">.</span><span class="nx">aboutToExpire</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">aboutToExpire</span><span class="p">,</span> <span class="nx">f</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="nf">AddAboutToExpireCallback</span><span class="p">(</span><span class="nx">f</span> <span class="kd">func</span><span class="p">(</span><span class="kd">interface</span><span class="p">{}))</span> <span class="p">{</span>
	<span class="nx">item</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">item</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>
	<span class="nx">item</span><span class="p">.</span><span class="nx">aboutToExpire</span> <span class="p">=</span> <span class="nb">append</span><span class="p">(</span><span class="nx">item</span><span class="p">.</span><span class="nx">aboutToExpire</span><span class="p">,</span> <span class="nx">f</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="nf">RemoveAboutToExpireCallback</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">item</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">item</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>
	<span class="nx">item</span><span class="p">.</span><span class="nx">aboutToExpire</span> <span class="p">=</span> <span class="kc">nil</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="2-缓存表cachetable">2. 缓存表CacheTable</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">CacheTable</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">sync</span><span class="p">.</span><span class="nx">RWMutex</span>

	<span class="c1">// 缓存表命名
</span><span class="c1"></span>	<span class="nx">name</span> <span class="kt">string</span>
	<span class="c1">// 缓存表内存储的所有元素，是个slice
</span><span class="c1"></span>	<span class="nx">items</span> <span class="kd">map</span><span class="p">[</span><span class="kd">interface</span><span class="p">{}]</span><span class="o">*</span><span class="nx">CacheItem</span>

	<span class="c1">// 触发清楚的定时器
</span><span class="c1"></span>	<span class="nx">cleanupTimer</span> <span class="o">*</span><span class="nx">time</span><span class="p">.</span><span class="nx">Timer</span>
	<span class="c1">// 当前定时器间隔
</span><span class="c1"></span>	<span class="nx">cleanupInterval</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Duration</span>

	<span class="nx">logger</span> <span class="o">*</span><span class="nx">log</span><span class="p">.</span><span class="nx">Logger</span>

	<span class="c1">// Callback method triggered when trying to load a non-existing key.
</span><span class="c1"></span>	<span class="nx">loadData</span> <span class="kd">func</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">args</span> <span class="o">...</span><span class="kd">interface</span><span class="p">{})</span> <span class="o">*</span><span class="nx">CacheItem</span>
	<span class="c1">// Callback method triggered when adding a new item to the cache.
</span><span class="c1"></span>	<span class="nx">addedItem</span> <span class="p">[]</span><span class="kd">func</span><span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span>
	<span class="c1">// Callback method triggered before deleting an item from the cache.
</span><span class="c1"></span>	<span class="nx">aboutToDeleteItem</span> <span class="p">[]</span><span class="kd">func</span><span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>同样的，涉及并发访问的属性，CacheTable的方法都会做上锁操作，比如以下方法，没有一一贴出来</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 获取元素个数
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">Count</span><span class="p">()</span> <span class="kt">int</span> <span class="p">{</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">table</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span>
	<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="nx">table</span><span class="p">.</span><span class="nx">items</span><span class="p">)</span>
<span class="p">}</span>

<span class="c1">// 遍历
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">Foreach</span><span class="p">(</span><span class="nx">trans</span> <span class="kd">func</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">))</span> <span class="p">{</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">table</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span>

	<span class="k">for</span> <span class="nx">k</span><span class="p">,</span> <span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">table</span><span class="p">.</span><span class="nx">items</span> <span class="p">{</span>
		<span class="nf">trans</span><span class="p">(</span><span class="nx">k</span><span class="p">,</span> <span class="nx">v</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="缓存表添加元素">缓存表添加元素</h6>

<p>添加新元素</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">Add</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">lifeSpan</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Duration</span><span class="p">,</span> <span class="nx">data</span> <span class="kd">interface</span><span class="p">{})</span> <span class="o">*</span><span class="nx">CacheItem</span> <span class="p">{</span>
	<span class="nx">item</span> <span class="o">:=</span> <span class="nf">NewCacheItem</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">lifeSpan</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span>

	<span class="c1">// Add item to cache.
</span><span class="c1"></span>	<span class="nx">table</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">addInternal</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>

	<span class="k">return</span> <span class="nx">item</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>添加不存在的元素</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">NotFoundAdd</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{},</span> <span class="nx">lifeSpan</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Duration</span><span class="p">,</span> <span class="nx">data</span> <span class="kd">interface</span><span class="p">{})</span> <span class="kt">bool</span> <span class="p">{</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>

	<span class="k">if</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">table</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span> <span class="nx">ok</span> <span class="p">{</span>
		<span class="nx">table</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>
		<span class="k">return</span> <span class="kc">false</span>
	<span class="p">}</span>

	<span class="c1">// 查找不到元素，则新建元素添加
</span><span class="c1"></span>	<span class="nx">item</span> <span class="o">:=</span> <span class="nf">NewCacheItem</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">lifeSpan</span><span class="p">,</span> <span class="nx">data</span><span class="p">)</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">addInternal</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>

	<span class="k">return</span> <span class="kc">true</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>添加元素均调用<code>addInternal</code>方法，调用此方法的前提是必须上锁，然后添加元素，并做过期检查</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">addInternal</span><span class="p">(</span><span class="nx">item</span> <span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span> <span class="p">{</span>
	<span class="c1">// Careful: do not run this method unless the table-mutex is locked!
</span><span class="c1"></span>	<span class="c1">// It will unlock it for the caller before running the callbacks and checks
</span><span class="c1"></span>	<span class="nx">table</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s">&#34;Adding item with key&#34;</span><span class="p">,</span> <span class="nx">item</span><span class="p">.</span><span class="nx">key</span><span class="p">,</span> <span class="s">&#34;and lifespan of&#34;</span><span class="p">,</span> <span class="nx">item</span><span class="p">.</span><span class="nx">lifeSpan</span><span class="p">,</span> <span class="s">&#34;to table&#34;</span><span class="p">,</span> <span class="nx">table</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span>
	<span class="nx">table</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="nx">item</span><span class="p">.</span><span class="nx">key</span><span class="p">]</span> <span class="p">=</span> <span class="nx">item</span>

	<span class="c1">// Cache values so we don&#39;t keep blocking the mutex.
</span><span class="c1"></span>	<span class="nx">expDur</span> <span class="o">:=</span> <span class="nx">table</span><span class="p">.</span><span class="nx">cleanupInterval</span>
	<span class="nx">addedItem</span> <span class="o">:=</span> <span class="nx">table</span><span class="p">.</span><span class="nx">addedItem</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>

	<span class="c1">// Trigger callback after adding an item to cache.
</span><span class="c1"></span>	<span class="k">if</span> <span class="nx">addedItem</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">callback</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">addedItem</span> <span class="p">{</span>
			<span class="nf">callback</span><span class="p">(</span><span class="nx">item</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="c1">// If we haven&#39;t set up any expiration check timer or found a more imminent item.
</span><span class="c1"></span>	<span class="k">if</span> <span class="nx">item</span><span class="p">.</span><span class="nx">lifeSpan</span> <span class="p">&gt;</span> <span class="mi">0</span> <span class="o">&amp;&amp;</span> <span class="p">(</span><span class="nx">expDur</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">item</span><span class="p">.</span><span class="nx">lifeSpan</span> <span class="p">&lt;</span> <span class="nx">expDur</span><span class="p">)</span> <span class="p">{</span>
		<span class="nx">table</span><span class="p">.</span><span class="nf">expirationCheck</span><span class="p">()</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="缓存表删除元素">缓存表删除元素</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">Delete</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">(</span><span class="o">*</span><span class="nx">CacheItem</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">table</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>

	<span class="k">return</span> <span class="nx">table</span><span class="p">.</span><span class="nf">deleteInternal</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>类似于添加元素方法，加锁后调用<code>deleteInternal</code>方法，先检查元素是否存在，在删除元素前，先确定有没有<code>aboutToDeleteItem</code>回调函数要调用，再对CacheItem上锁删除</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">deleteInternal</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">(</span><span class="o">*</span><span class="nx">CacheItem</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
	<span class="nx">r</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">table</span><span class="p">.</span><span class="nx">items</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span>
	<span class="k">if</span> <span class="p">!</span><span class="nx">ok</span> <span class="p">{</span>
		<span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">ErrKeyNotFound</span>
	<span class="p">}</span>

	<span class="c1">// Cache value so we don&#39;t keep blocking the mutex.
</span><span class="c1"></span>	<span class="nx">aboutToDeleteItem</span> <span class="o">:=</span> <span class="nx">table</span><span class="p">.</span><span class="nx">aboutToDeleteItem</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>

	<span class="c1">// Trigger callbacks before deleting an item from cache.
</span><span class="c1"></span>	<span class="k">if</span> <span class="nx">aboutToDeleteItem</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">callback</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">aboutToDeleteItem</span> <span class="p">{</span>
			<span class="nf">callback</span><span class="p">(</span><span class="nx">r</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="nx">r</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">r</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span>
	<span class="k">if</span> <span class="nx">r</span><span class="p">.</span><span class="nx">aboutToExpire</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">callback</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">r</span><span class="p">.</span><span class="nx">aboutToExpire</span> <span class="p">{</span>
			<span class="nf">callback</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="nx">table</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s">&#34;Deleting item with key&#34;</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="s">&#34;created on&#34;</span><span class="p">,</span> <span class="nx">r</span><span class="p">.</span><span class="nx">createdOn</span><span class="p">,</span> <span class="s">&#34;and hit&#34;</span><span class="p">,</span> <span class="nx">r</span><span class="p">.</span><span class="nx">accessCount</span><span class="p">,</span> <span class="s">&#34;times from table&#34;</span><span class="p">,</span> <span class="nx">table</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span>
	<span class="nb">delete</span><span class="p">(</span><span class="nx">table</span><span class="p">.</span><span class="nx">items</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span>

	<span class="k">return</span> <span class="nx">r</span><span class="p">,</span> <span class="kc">nil</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="元素过期检查机制">元素过期检查机制</h6>

<ul>
<li><code>lifeSpan</code>为0的元素永久保留</li>

<li><p>通过元素的<code>accessedOn</code>属性判断是否过期，已过期则删除，未过期更新剩余生命时长</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">expirationCheck</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="k">if</span> <span class="nx">table</span><span class="p">.</span><span class="nx">cleanupTimer</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">table</span><span class="p">.</span><span class="nx">cleanupTimer</span><span class="p">.</span><span class="nf">Stop</span><span class="p">()</span>
	<span class="p">}</span>
	<span class="k">if</span> <span class="nx">table</span><span class="p">.</span><span class="nx">cleanupInterval</span> <span class="p">&gt;</span> <span class="mi">0</span> <span class="p">{</span>
		<span class="nx">table</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s">&#34;Expiration check triggered after&#34;</span><span class="p">,</span> <span class="nx">table</span><span class="p">.</span><span class="nx">cleanupInterval</span><span class="p">,</span> <span class="s">&#34;for table&#34;</span><span class="p">,</span> <span class="nx">table</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span>
	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
		<span class="nx">table</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s">&#34;Expiration check installed for table&#34;</span><span class="p">,</span> <span class="nx">table</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span>
	<span class="p">}</span>

	<span class="c1">// To be more accurate with timers, we would need to update &#39;now&#39; on every
</span><span class="c1"></span>	<span class="c1">// loop iteration. Not sure it&#39;s really efficient though.
</span><span class="c1"></span>	<span class="nx">now</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Now</span><span class="p">()</span>
	<span class="nx">smallestDuration</span> <span class="o">:=</span> <span class="mi">0</span> <span class="o">*</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Second</span>
	<span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">item</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">table</span><span class="p">.</span><span class="nx">items</span> <span class="p">{</span>
		<span class="c1">// Cache values so we don&#39;t keep blocking the mutex.
</span><span class="c1"></span>		<span class="nx">item</span><span class="p">.</span><span class="nf">RLock</span><span class="p">()</span>
		<span class="nx">lifeSpan</span> <span class="o">:=</span> <span class="nx">item</span><span class="p">.</span><span class="nx">lifeSpan</span>
		<span class="nx">accessedOn</span> <span class="o">:=</span> <span class="nx">item</span><span class="p">.</span><span class="nx">accessedOn</span>
		<span class="nx">item</span><span class="p">.</span><span class="nf">RUnlock</span><span class="p">()</span>

		<span class="c1">// 为0的元素永久保留
</span><span class="c1"></span>		<span class="k">if</span> <span class="nx">lifeSpan</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
			<span class="k">continue</span>
		<span class="p">}</span>

		<span class="c1">// 通过元素的`accessedOn`属性判断是否过期，已过期则删除
</span><span class="c1"></span>		<span class="k">if</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Sub</span><span class="p">(</span><span class="nx">accessedOn</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="nx">lifeSpan</span> <span class="p">{</span>
			<span class="c1">// Item has excessed its lifespan.
</span><span class="c1"></span>			<span class="nx">table</span><span class="p">.</span><span class="nf">deleteInternal</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span>
		<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
			<span class="c1">// 未过期更新剩余生命时长
</span><span class="c1"></span>			<span class="c1">// Find the item chronologically closest to its end-of-lifespan.
</span><span class="c1"></span>			<span class="k">if</span> <span class="nx">smallestDuration</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">lifeSpan</span><span class="o">-</span><span class="nx">now</span><span class="p">.</span><span class="nf">Sub</span><span class="p">(</span><span class="nx">accessedOn</span><span class="p">)</span> <span class="p">&lt;</span> <span class="nx">smallestDuration</span> <span class="p">{</span>
				<span class="nx">smallestDuration</span> <span class="p">=</span> <span class="nx">lifeSpan</span> <span class="o">-</span> <span class="nx">now</span><span class="p">.</span><span class="nf">Sub</span><span class="p">(</span><span class="nx">accessedOn</span><span class="p">)</span>
			<span class="p">}</span>
		<span class="p">}</span>
	<span class="p">}</span>

	<span class="c1">// Setup the interval for the next cleanup run.
</span><span class="c1"></span>	<span class="nx">table</span><span class="p">.</span><span class="nx">cleanupInterval</span> <span class="p">=</span> <span class="nx">smallestDuration</span>
	<span class="k">if</span> <span class="nx">smallestDuration</span> <span class="p">&gt;</span> <span class="mi">0</span> <span class="p">{</span>
		<span class="nx">table</span><span class="p">.</span><span class="nx">cleanupTimer</span> <span class="p">=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">AfterFunc</span><span class="p">(</span><span class="nx">smallestDuration</span><span class="p">,</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
			<span class="k">go</span> <span class="nx">table</span><span class="p">.</span><span class="nf">expirationCheck</span><span class="p">()</span>
		<span class="p">})</span>
	<span class="p">}</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div></li>
</ul>

<h6 id="缓存表清空">缓存表清空</h6>

<p>关闭定时器，存放元素的map指向一个空map即可</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">table</span> <span class="o">*</span><span class="nx">CacheTable</span><span class="p">)</span> <span class="nf">Flush</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">table</span><span class="p">.</span><span class="nf">Lock</span><span class="p">()</span>
	<span class="k">defer</span> <span class="nx">table</span><span class="p">.</span><span class="nf">Unlock</span><span class="p">()</span>

	<span class="nx">table</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="s">&#34;Flushing table&#34;</span><span class="p">,</span> <span class="nx">table</span><span class="p">.</span><span class="nx">name</span><span class="p">)</span>

	<span class="nx">table</span><span class="p">.</span><span class="nx">items</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kd">interface</span><span class="p">{}]</span><span class="o">*</span><span class="nx">CacheItem</span><span class="p">)</span>
	<span class="nx">table</span><span class="p">.</span><span class="nx">cleanupInterval</span> <span class="p">=</span> <span class="mi">0</span>
	<span class="k">if</span> <span class="nx">table</span><span class="p">.</span><span class="nx">cleanupTimer</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
		<span class="nx">table</span><span class="p">.</span><span class="nx">cleanupTimer</span><span class="p">.</span><span class="nf">Stop</span><span class="p">()</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/">源码阅读</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/cache2go/">cache2go</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>写在2019年最后</title>
                <link>https://jjmeg.github.io/posts/2019-summary/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/2019-summary/</guid>
                <pubDate>Mon, 30 Dec 2019 16:23:29 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>🕚</center></p>

<p style="text-indent:2em">2019年3月，签三方；</p>

<p style="text-indent:2em">2019年6月，毕业；</p>

<p style="text-indent:2em">2019年7月，正式到岗；</p>

<p style="text-indent:2em">2019年要结束了。</p>

<h3 id="这半年做了什么">这半年做了什么？</h3>

<p style="text-indent:2em">进入新行业，了解新领域；</p>

<p style="text-indent:2em">CRUD；</p>

<p style="text-indent:2em">自我规范；</p>

<p style="text-indent:2em">心态建设；</p>

<p style="text-indent:2em">经营爱好；</p>

<p style="text-indent:2em">健身。</p>

<h3 id="对创新型产品的看法">对创新型产品的看法</h3>

<p style="text-indent:2em">大饼；</p>

<p style="text-indent:2em">新人雷区；</p>

<p style="text-indent:2em">看清该产品的战略地位；</p>

<p style="text-indent:2em">是否有高层大力支持；</p>

<p style="text-indent:2em">不要想着能快速变现；</p>

<p style="text-indent:2em">稳定的产品和业务才是王道。</p>

<h3 id="2020年">2020年</h3>

<p style="text-indent:2em">Enjoy it!</p>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/%E7%A2%8E%E5%BF%B5/">碎念</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--通道Channel</title>
                <link>https://jjmeg.github.io/posts/golang-channel/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-channel/</guid>
                <pubDate>Wed, 18 Dec 2019 11:31:10 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「channel」</center>
<p style="text-indent:2em">channel 通道，goroutine是实现并发的手段，常用于goroutine之间同步消息，发送和接收消息，可视为一个队列，实质是在goroutine之间共享内存。</p></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📚<a href="#channel的声明及初始化">channel的声明及初始化</a></li>
<li>📚<a href="#channel存取数据及关闭">channel存取数据及关闭</a></li>
<li>📚<a href="#非缓冲channel">非缓冲channel</a>

<ul>
<li>📖<a href="#channel阻塞goroutine">channel阻塞goroutine</a></li>
<li>📖<a href="#无缓冲channel引起的死锁案例">无缓冲channel引起的死锁案例</a></li>
</ul></li>
<li>📚<a href="#缓冲channel">缓冲channel</a></li>
</ul>

<hr />

<h3 id="channel的声明及初始化">🐵channel的声明及初始化</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">//声明
</span><span class="c1"></span><span class="kd">var</span> <span class="nx">ch</span> <span class="kd">chan</span> <span class="nx">类型</span>
<span class="c1">//初始化
</span><span class="c1"></span><span class="nx">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="nx">类型</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">var</span> <span class="nx">ch</span> <span class="kd">chan</span> <span class="kt">int</span>
<span class="nx">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="channel存取数据及关闭">🐵channel存取数据及关闭</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="nx">ch</span> <span class="o">&lt;-</span> <span class="nx">x</span> <span class="c1">//往channel中存入数据 x
</span><span class="c1"></span><span class="o">&lt;-</span> <span class="nx">ch</span> <span class="c1">// 从channel中取出数据
</span><span class="c1"></span><span class="nx">x</span> <span class="o">&lt;-</span> <span class="nx">ch</span> <span class="c1">//从channel中取出数据并赋值给 x
</span><span class="c1"></span><span class="nb">close</span><span class="p">(</span><span class="nx">ch</span><span class="p">)</span> <span class="o">//</span> <span class="nx">关闭通道</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="非缓冲channel">🐵非缓冲channel</h3>

<p>channel中只存储一个数据</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 这个channel中只存储一个数据
</span><span class="c1"></span><span class="kd">var</span> <span class="nx">ch</span> <span class="kd">chan</span> <span class="kt">int</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span>
<span class="c1">// 等同于
</span><span class="c1"></span><span class="kd">var</span> <span class="nx">ch</span> <span class="kd">chan</span> <span class="kt">int</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

<span class="kd">func</span> <span class="nf">foo</span><span class="p">()</span>  <span class="p">{</span>
	<span class="nx">ch</span> <span class="o">&lt;-</span> <span class="mi">0</span><span class="c1">//存消息，如果没有其他goroutine来取走这个数据，那么挂起foo，直到main函数把这个0取走
</span><span class="c1"></span><span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="k">go</span> <span class="nf">foo</span><span class="p">()</span>
	<span class="o">&lt;-</span> <span class="nx">ch</span><span class="c1">//从ch取消息，如果ch中没有数据，就挂起main线程，直到foo函数往ch内放数据
</span><span class="c1"></span><span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>问题：goroutine已经执行完毕了如何去通知main线程？</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">var</span> <span class="nx">complete</span> <span class="kd">chan</span> <span class="kt">int</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span>

<span class="kd">func</span> <span class="nf">loop</span><span class="p">()</span>  <span class="p">{</span>
	<span class="k">for</span> <span class="nx">i</span><span class="o">:=</span><span class="mi">0</span> <span class="p">;</span> <span class="nx">i</span><span class="p">&lt;</span><span class="mi">10</span> <span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Print</span><span class="p">(</span><span class="s">&#34;%d&#34;</span><span class="p">,</span><span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>
	<span class="nx">complete</span> <span class="o">&lt;-</span> <span class="mi">0</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="k">go</span> <span class="nf">loop</span><span class="p">()</span>
	<span class="o">&lt;-</span> <span class="nx">complete</span> <span class="c1">//直到线程跑完，取到消息
</span><span class="c1"></span><span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="channel阻塞goroutine">🐒channel阻塞goroutine</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">var</span> <span class="nx">channel</span> <span class="kd">chan</span> <span class="kt">int</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="kd">var</span> <span class="nx">messages</span> <span class="kd">chan</span> <span class="kt">string</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">string</span><span class="p">)</span>
	<span class="k">go</span> <span class="kd">func</span> <span class="p">(</span><span class="nx">message</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
		<span class="nx">messages</span> <span class="o">&lt;-</span> <span class="nx">message</span> <span class="c1">// channel存消息
</span><span class="c1"></span>    <span class="c1">// 若未取出这条消息，这个协程将被阻塞
</span><span class="c1"></span>	<span class="p">}</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="o">&lt;-</span><span class="nx">messages</span><span class="p">)</span><span class="c1">//channel取消息，消息被取后，阻塞解除
</span><span class="c1"></span><span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<ul>
<li>取数据：无缓冲的信道不存储数据，只负责数据的流通，从信道取数据时，若没有数据在信道中，那么当前线程阻塞</li>
<li>存数据：没有其他goroutine拿走数据，数据还在信道中，当前这个线程也阻塞</li>
</ul>

<h6 id="无缓冲channel引起的死锁案例">🐒无缓冲channel引起的死锁案例</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">//例子1
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="kd">var</span> <span class="nx">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span><span class="p">,</span><span class="kt">int</span><span class="p">)</span>
	<span class="nx">ch</span> <span class="o">&lt;-</span> <span class="mi">1</span><span class="c1">//死锁了，没有线程取走这个数据
</span><span class="c1"></span>	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;wrong&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="c1">//例子2
</span><span class="c1"></span><span class="kd">var</span> <span class="nx">ch1</span> <span class="kd">chan</span> <span class="kt">int</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span>
<span class="kd">var</span> <span class="nx">ch2</span> <span class="kd">chan</span> <span class="kt">int</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span>
<span class="kd">func</span> <span class="nf">say</span><span class="p">(</span><span class="nx">s</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">s</span><span class="p">)</span>
	<span class="nx">ch1</span> <span class="o">&lt;-</span> <span class="o">&lt;-</span> <span class="nx">ch2</span><span class="c1">//ch1等待ch2的输出
</span><span class="c1"></span><span class="p">}</span>
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="k">go</span> <span class="nf">say</span><span class="p">(</span><span class="s">&#34;hello&#34;</span><span class="p">)</span>
	<span class="o">&lt;-</span> <span class="nx">ch1</span>
<span class="p">}</span>

<span class="c1">//例子3
</span><span class="c1"></span><span class="nx">c</span><span class="p">,</span> <span class="nx">quit</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">),</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span>
<span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
   <span class="nx">c</span> <span class="o">&lt;-</span> <span class="mi">1</span>  <span class="c1">// c通道的数据没有被其他goroutine读取走 堵塞当前goroutine
</span><span class="c1"></span>   <span class="nx">quit</span> <span class="o">&lt;-</span> <span class="mi">0</span> <span class="c1">// quit始终没有办法写入数据
</span><span class="c1"></span><span class="p">}()</span>
<span class="o">&lt;-</span> <span class="nx">quit</span> <span class="c1">// quit 等待数据的写
</span><span class="c1"></span>
<span class="c1">//反例
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">c</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">)</span>
    <span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span>
       <span class="nx">c</span> <span class="o">&lt;-</span> <span class="mi">1</span>
    <span class="p">}()</span>
<span class="p">}</span><span class="o">//</span><span class="nx">main未等待其他goroutine</span> <span class="nx">自己先运行完毕了</span> <span class="nx">没有数据流入c通道</span> <span class="nx">一共执行了一个goroutine</span> <span class="nx">没有阻塞</span> <span class="nx">没有死锁</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="缓冲channel">🐵缓冲channel</h3>

<p>容量未满不会阻塞，无缓冲信道从不存储数据，流入的数据必须流出才行，否则将阻塞当前线程</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">var</span> <span class="nx">ch</span> <span class="kd">chan</span> <span class="kt">int</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span> <span class="c1">// 写入2个元素都不会阻塞当前goroutine, 存储个数达到2的时候会阻塞
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="kt">int</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
    <span class="nx">ch</span> <span class="o">&lt;-</span> <span class="mi">1</span>
    <span class="nx">ch</span> <span class="o">&lt;-</span> <span class="mi">2</span>
    <span class="nx">ch</span> <span class="o">&lt;-</span> <span class="mi">3</span>
<span class="p">}</span><span class="o">//</span><span class="nx">若再流入一个数据</span> <span class="nx">信道ch会阻塞main线程</span> <span class="nx">报死锁</span></code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--协程Goroutine</title>
                <link>https://jjmeg.github.io/posts/golang-goroutine/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-goroutine/</guid>
                <pubDate>Tue, 17 Dec 2019 10:02:21 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「goroutine」</center>
<p style="text-indent:2em">Go中实现并发的手段，Goroutine的创建和销毁的代价更小，调度也独立于线程，因此Goroutine可视为轻量级的线程，又称协程。</p></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📚<a href="#goroutine的声明">goroutine的声明</a></li>
<li>📚<a href="#goroutine例子">goroutine例子</a>

<ul>
<li>📖<a href="#未引入goroutine">未引入goroutine</a></li>
<li>📖<a href="#引入goroutine">引入goroutine</a></li>
<li>📖<a href="#实现goroutine结束">实现goroutine结束</a></li>
</ul></li>
</ul>

<hr />

<h3 id="goroutine的声明">goroutine的声明</h3>

<p>在函数前添加<code>go</code>关键字即可</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="nf">say</span><span class="p">(){</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;hello world&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
  <span class="nf">say</span><span class="p">()</span>
  <span class="k">go</span> <span class="nf">say</span><span class="p">()</span><span class="c1">// 创建了一个新协程
</span><span class="c1"></span><span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="goroutine例子">goroutine例子</h3>

<h6 id="未引入goroutine">未引入goroutine</h6>

<p>程序串行执行</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">loop</span><span class="p">(</span><span class="nx">round</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;=</span><span class="mi">3</span> <span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Round:%s,\ti:%d\n&#34;</span><span class="p">,</span><span class="nx">round</span><span class="p">,</span><span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="nf">loop</span><span class="p">(</span><span class="s">&#34;A&#34;</span><span class="p">)</span>
	<span class="nf">loop</span><span class="p">(</span><span class="s">&#34;B&#34;</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>loop是按顺序执行的，先执行loop(1)，再执行loop(2)</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Round:A,	i:1
Round:A,	i:2
Round:A,	i:3
Round:B,	i:1
Round:B,	i:2
Round:B,	i:3</code></pre></td></tr></table>
</div>
</div>
<h6 id="引入goroutine">引入goroutine</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">loop</span><span class="p">(</span><span class="nx">round</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;=</span><span class="mi">3</span> <span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Round:%s,\ti:%d\n&#34;</span><span class="p">,</span><span class="nx">round</span><span class="p">,</span><span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="k">go</span> <span class="nf">loop</span><span class="p">(</span><span class="s">&#34;B&#34;</span><span class="p">)</span>
  <span class="nf">loop</span><span class="p">(</span><span class="s">&#34;A&#34;</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>只运行了A轮结果，主线程运行，主线程也是一个goroutine，loop(&quot;A&quot;)在主线程中
中运行loop(&quot;A&quot;)，新起一个goroutine运行loop(&quot;B&quot;)，goroutine没来得及跑loop(&quot;B&quot;)，主线程已经结束，所以只有loop(&quot;A&quot;)的结果</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Round:A,	i:1
Round:A,	i:2
Round:A,	i:3</code></pre></td></tr></table>
</div>
</div>
<h6 id="等待goroutine结束">等待goroutine结束</h6>

<p><strong>1. 主线程等待</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
  <span class="s">&#34;fmt&#34;</span>
  <span class="s">&#34;time&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">loop</span><span class="p">(</span><span class="nx">round</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;=</span><span class="mi">3</span> <span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Round:%s,\ti:%d\n&#34;</span><span class="p">,</span><span class="nx">round</span><span class="p">,</span><span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
	<span class="k">go</span> <span class="nf">loop</span><span class="p">(</span><span class="s">&#34;B&#34;</span><span class="p">)</span>
  <span class="nf">loop</span><span class="p">(</span><span class="s">&#34;A&#34;</span><span class="p">)</span>
  <span class="k">go</span> <span class="nf">loop</span><span class="p">(</span><span class="s">&#34;C&#34;</span><span class="p">)</span>
  <span class="nx">time</span><span class="p">.</span><span class="nf">Sleep</span><span class="p">(</span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>先运行A轮再运行B轮，主线程建立后，新起一个goroutine运行loop(&quot;B&quot;)，主线程执行A轮，A轮执行完，有一秒钟等待时间，goroutine来得及跑loop(&quot;B&quot;)，再出现B轮的结果</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Round:A,	i:1
Round:A,	i:2
Round:A,	i:3
Round:B,	i:1
Round:B,	i:2
Round:B,	i:3</code></pre></td></tr></table>
</div>
</div>
<p><strong>2. 使用sync.WaitGroup实现等待goroutine结束</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="p">(</span>
    <span class="s">&#34;fmt&#34;</span>
    <span class="s">&#34;sync&#34;</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">goRun</span><span class="p">(</span><span class="nx">round</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">wg</span> <span class="o">*</span><span class="nx">sync</span><span class="p">.</span><span class="nx">WaitGroup</span><span class="p">)</span>  <span class="p">{</span>
  <span class="k">defer</span> <span class="nx">wg</span><span class="p">.</span><span class="nf">Done</span><span class="p">()</span>
  <span class="nf">loop</span><span class="p">(</span><span class="nx">round</span><span class="p">)</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="nf">loop</span><span class="p">(</span><span class="nx">round</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
	<span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span><span class="o">&lt;=</span><span class="mi">3</span> <span class="p">;</span><span class="nx">i</span><span class="o">++</span><span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Round:%s,\ti:%d\n&#34;</span><span class="p">,</span><span class="nx">round</span><span class="p">,</span><span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span>  <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">wg</span> <span class="nx">sync</span><span class="p">.</span><span class="nx">WaitGroup</span>

  <span class="nx">wg</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
  <span class="k">go</span> <span class="nf">goRun</span><span class="p">(</span><span class="s">&#34;A&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="nx">wg</span><span class="p">)</span>
  <span class="k">go</span> <span class="nf">goRun</span><span class="p">(</span><span class="s">&#34;B&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="nx">wg</span><span class="p">)</span>
  <span class="k">go</span> <span class="nf">goRun</span><span class="p">(</span><span class="s">&#34;C&#34;</span><span class="p">,</span><span class="o">&amp;</span><span class="nx">wg</span><span class="p">)</span>

  <span class="nx">wg</span><span class="p">.</span><span class="nf">Wait</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>使用 <code>sync.WaitGroup</code> 来完成等待的操作，比起<code>time.Sleep()</code>更灵活，这种等待是协程之间实现同步的办法</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Round:C,	i:1
Round:C,	i:2
Round:C,	i:3
Round:A,	i:1
Round:A,	i:2
Round:A,	i:3
Round:B,	i:1
Round:B,	i:2
Round:B,	i:3</code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--接口Interface</title>
                <link>https://jjmeg.github.io/posts/golang-interface/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-interface/</guid>
                <pubDate>Tue, 17 Dec 2019 09:52:40 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「interface」</center>
<p style="text-indent:2em">接口，即一些方法的集合，在Go中，interface也是一种类型，属于指针类型，常用接口实现多态。</p></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📚<a href="#interface的声明">interface的声明</a></li>
<li>📚<a href="#interface的实现">interface的实现</a></li>
<li>📚<a href="#interface嵌套">interface嵌套</a></li>
</ul>

<hr />

<h3 id="interface的声明">🐵interface的声明</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">接口名</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nx">方法1</span>
  <span class="nx">方法2</span>
  <span class="o">...</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">AInterface</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nf">Say</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="interface的实现">🐵interface的实现</h3>

<p><strong>1. 接口中所有的方法没有方法体，都没有实现细节，也不能包含变量</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">AInterface</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nf">Say</span><span class="p">()</span>
  <span class="nx">Name</span> <span class="kt">string</span> <span class="c1">//这里会报错，不可以包含变量
</span><span class="c1"></span><span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>2. 接口不能创建实例，但可以指向一个自定义类型的变量，只要是自定义类型均可以实现接口，例如结构体可以实现接口</strong></p>

<ul>
<li><p>错误示例：非自定义类型实现自定义接口
int类型是Go的内置类型，我们自定义的AInterface接口在Go中未实现，因此自定义接口需要由自定义的类型实现</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">AInterface</span> <span class="kd">interface</span><span class="p">{</span>
<span class="nf">Say</span><span class="p">()</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">i</span> <span class="kt">int</span><span class="p">)</span> <span class="nf">Say</span><span class="p">(){</span><span class="c1">// 这里报错：cannot define new methods on non-local type int
</span><span class="c1"></span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;hello&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">i</span> <span class="kt">int</span> <span class="p">=</span> <span class="mi">10</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="nx">AInterface</span> <span class="p">=</span> <span class="nx">i</span> <span class="c1">// cannot use i (type int) as type AInterface in assignment:
</span><span class="c1"></span>	                     <span class="c1">// int does not implement AInterface (missing Say method)
</span><span class="c1"></span><span class="nx">b</span><span class="p">.</span><span class="nf">Say</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div></li>

<li><p>正确示例：自定义类型实现自定义接口</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">AInterface</span> <span class="kd">interface</span><span class="p">{</span>
<span class="nf">Say</span><span class="p">()</span>
<span class="p">}</span>

<span class="c1">// 自定义了类型integer
</span><span class="c1"></span><span class="kd">type</span> <span class="nx">integer</span> <span class="kt">int</span>

<span class="c1">// 用integer去实现AInterface接口
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">i</span> <span class="nx">integer</span><span class="p">)</span> <span class="nf">Say</span><span class="p">(){</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;hello&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">i</span> <span class="nx">integer</span> <span class="p">=</span> <span class="mi">10</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="nx">AInterface</span> <span class="p">=</span> <span class="nx">i</span>
<span class="nx">b</span><span class="p">.</span><span class="nf">Say</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">hello</code></pre></td></tr></table>
</div>
</div></li>
</ul>

<p><strong>3. 实现某个接口中的所有方法才能称得上是接口实现</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">AInterface</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nf">Say</span><span class="p">()</span>
  <span class="nf">Write</span><span class="p">()</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">integer</span> <span class="kt">int</span>

<span class="c1">// 用integer去只实现了接口中的Say方法
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">i</span> <span class="nx">integer</span><span class="p">)</span> <span class="nf">Say</span><span class="p">(){</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;hello&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
  <span class="kd">var</span> <span class="nx">i</span> <span class="nx">integer</span> <span class="p">=</span> <span class="mi">10</span>
  <span class="kd">var</span> <span class="nx">b</span> <span class="nx">AInterface</span> <span class="p">=</span> <span class="nx">i</span>
  <span class="nx">b</span><span class="p">.</span><span class="nf">Say</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>由于只实现了部分方法，编译将报错，提示未实现Write方法</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">cannot use i <span class="o">(</span><span class="nb">type</span> integer<span class="o">)</span> as <span class="nb">type</span> AInterface in assignment:
	integer does not implement AInterface <span class="o">(</span>missing Write method<span class="o">)</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>4. 一个自定义类型可以实现多个接口</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">AInterface</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nf">Say</span><span class="p">()</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">BInterface</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nf">Write</span><span class="p">()</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">integer</span> <span class="kt">int</span>

<span class="c1">// 实现AInterface接口
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">i</span> <span class="nx">integer</span><span class="p">)</span> <span class="nf">Say</span><span class="p">(){</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;hello&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="c1">// 同时实现BInterface接口B
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">i</span> <span class="nx">integer</span><span class="p">)</span> <span class="nf">Write</span><span class="p">(){</span>
   <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;world&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
  <span class="kd">var</span> <span class="nx">i</span> <span class="nx">integer</span> <span class="p">=</span> <span class="mi">10</span>
  <span class="kd">var</span> <span class="nx">b</span> <span class="nx">AInterface</span> <span class="p">=</span> <span class="nx">i</span>
  <span class="nx">b</span><span class="p">.</span><span class="nf">Say</span><span class="p">()</span>

  <span class="kd">var</span> <span class="nx">c</span> <span class="nx">BInterface</span> <span class="p">=</span> <span class="nx">i</span>
  <span class="nx">c</span><span class="p">.</span><span class="nf">Write</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">hello
world</code></pre></td></tr></table>
</div>
</div>
<h3 id="interface嵌套">🐵interface嵌套</h3>

<p>接口可以嵌套接口，但实现接口时必须全部实现</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">AInterface</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nf">Say</span><span class="p">()</span>
  <span class="nx">BInterface</span><span class="c1">//嵌套B接口
</span><span class="c1"></span><span class="p">}</span>

<span class="kd">type</span> <span class="nx">BInterface</span> <span class="kd">interface</span><span class="p">{</span>
  <span class="nf">Write</span><span class="p">()</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">integer</span> <span class="kt">int</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">i</span> <span class="nx">integer</span><span class="p">)</span> <span class="nf">Say</span><span class="p">(){</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;hello&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="p">(</span><span class="nx">i</span> <span class="nx">integer</span><span class="p">)</span> <span class="nf">Write</span><span class="p">(){</span>
   <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;world&#34;</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
  <span class="kd">var</span> <span class="nx">i</span> <span class="nx">integer</span> <span class="p">=</span> <span class="mi">10</span>
  <span class="kd">var</span> <span class="nx">b</span> <span class="nx">AInterface</span> <span class="p">=</span> <span class="nx">i</span>
  <span class="nx">b</span><span class="p">.</span><span class="nf">Say</span><span class="p">()</span>

  <span class="kd">var</span> <span class="nx">c</span> <span class="nx">BInterface</span> <span class="p">=</span> <span class="nx">i</span>
  <span class="nx">c</span><span class="p">.</span><span class="nf">Write</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--结构体struct和方法method</title>
                <link>https://jjmeg.github.io/posts/golang-struct-and-method/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-struct-and-method/</guid>
                <pubDate>Fri, 13 Dec 2019 15:02:59 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「struct💞method」</center>
<p style="text-indent:2em">Go没有类的概念，将多个不同类型的数据集合在一起，可以用到struct，method则是赋给某变量的函数。</p></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📚<a href="#struct">struct</a>

<ul>
<li>📖<a href="#struct的声明">struct的声明</a></li>
<li>📖<a href="#struct的初始化">struct的初始化</a></li>
<li>📖<a href="#struct的嵌套">struct的嵌套</a></li>
<li>📖<a href="#成员的可见性">成员的可见性</a></li>
</ul></li>
<li>📚<a href="#method">method</a>

<ul>
<li>📖<a href="#method的声明">method的声明</a></li>
<li>📖<a href="#一些约束">一些约束</a></li>
</ul></li>
</ul>

<hr />

<h1 id="struct">🐵struct</h1>

<h6 id="struct的声明">🐒struct的声明</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">结构名</span> <span class="kd">struct</span><span class="p">{</span>
  <span class="nx">变量名1</span> <span class="nx">变量类型</span>
  <span class="nx">变量名2</span> <span class="nx">变量类型</span>
  <span class="o">...</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>例如</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>     <span class="kt">string</span>
	<span class="nx">Age</span>      <span class="kt">int</span>
	<span class="nx">Region</span>   <span class="kt">string</span>
<span class="p">}</span>
<span class="c1">// 也可以简写为
</span><span class="c1"></span><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span><span class="p">,</span> <span class="nx">Region</span>   <span class="kt">string</span>
	<span class="nx">Age</span>              <span class="kt">int</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="struct的初始化">🐒struct的初始化</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>     <span class="kt">string</span>
	<span class="nx">Age</span>      <span class="kt">int</span>
	<span class="nx">Region</span>   <span class="kt">string</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// 声明
</span><span class="c1"></span>  <span class="c1">// 1. 指定变量类型
</span><span class="c1"></span>	<span class="kd">var</span> <span class="nx">amy</span> <span class="nx">Person</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">amy</span><span class="p">)</span>

  <span class="c1">// 2. 构造空结构体，也可以完成声明
</span><span class="c1"></span>  <span class="nx">lily</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{}</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">lily</span><span class="p">)</span>

  <span class="c1">// 结构体变量初始化
</span><span class="c1"></span>  <span class="c1">// 1. 对相应字段赋值
</span><span class="c1"></span>	<span class="nx">amy</span><span class="p">.</span><span class="nx">Name</span> <span class="p">=</span> <span class="s">&#34;amy&#34;</span>
	<span class="nx">amy</span><span class="p">.</span><span class="nx">Age</span> <span class="p">=</span> <span class="mi">10</span>
	<span class="nx">amy</span><span class="p">.</span><span class="nx">Region</span> <span class="p">=</span> <span class="s">&#34;China&#34;</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">amy</span><span class="p">)</span>

  <span class="c1">// 2. 直接写在结构体中
</span><span class="c1"></span>  <span class="nx">lily</span> <span class="p">=</span> <span class="nx">Person</span><span class="p">{</span>
    <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;lily&#34;</span><span class="p">,</span>
    <span class="nx">Age</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
    <span class="nx">Region</span><span class="p">:</span> <span class="s">&#34;China&#34;</span><span class="p">,</span>
  <span class="p">}</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">lily</span><span class="p">)</span>

  <span class="c1">// 修改结构体中的变量
</span><span class="c1"></span>	<span class="kd">var</span> <span class="nx">p</span> <span class="p">=</span> <span class="o">&amp;</span><span class="nx">amy</span>
	<span class="nx">p</span><span class="p">.</span><span class="nx">Region</span> <span class="p">=</span> <span class="s">&#34;USA&#34;</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">amy</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"><span class="o">{</span> <span class="m">0</span> <span class="o">}</span>
<span class="o">{</span> <span class="m">0</span> <span class="o">}</span>
<span class="o">{</span>amy <span class="m">10</span> China<span class="o">}</span>
<span class="o">{</span>lily <span class="m">10</span> China<span class="o">}</span>
<span class="o">{</span>amy <span class="m">10</span> USA<span class="o">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="struct的嵌套">🐒struct的嵌套</h6>

<p><strong>1. 嵌入本身的结构体，使用指针嵌入</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">Tree</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Value</span>     <span class="kt">int</span>
	<span class="nx">Left</span>      <span class="o">*</span><span class="nx">Tree</span>
	<span class="nx">Right</span>     <span class="o">*</span><span class="nx">Tree</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>2. 嵌入其他结构体</strong></p>

<p>变相实现了继承，Person拥有了Region的所有属性</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Name</span>      <span class="kt">string</span>
  <span class="nx">Age</span>       <span class="kt">int</span>
  <span class="nx">Location</span>  <span class="nx">Region</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">Region</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Country</span> <span class="kt">string</span>
  <span class="nx">City</span>    <span class="kt">string</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>3. 嵌入匿名成员</strong></p>

<p>匿名成员即没有变量命名的成员，可以直接访问匿名成员结构体内的变量</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Name</span>      <span class="kt">string</span>
  <span class="nx">Age</span>       <span class="kt">int</span>
  <span class="nx">Region</span>
<span class="p">}</span>

<span class="kd">type</span> <span class="nx">Region</span> <span class="kd">struct</span> <span class="p">{</span>
  <span class="nx">Country</span> <span class="kt">string</span>
  <span class="nx">City</span>    <span class="kt">string</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

  <span class="nx">region</span> <span class="o">:=</span> <span class="nx">Region</span><span class="p">{</span>
    <span class="nx">Country</span><span class="p">:</span>  <span class="s">&#34;China&#34;</span><span class="p">,</span>
    <span class="nx">City</span><span class="p">:</span>     <span class="s">&#34;Beijing&#34;</span><span class="p">,</span>
  <span class="p">}</span>

  <span class="nx">lily</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span>
    <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;lily&#34;</span><span class="p">,</span>
    <span class="nx">Age</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
    <span class="nx">Region</span><span class="p">:</span> <span class="nx">region</span><span class="p">,</span>
  <span class="p">}</span>

  <span class="c1">// 可以直接访问Region中的Country和City
</span><span class="c1"></span>  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Her country is: &#34;</span><span class="p">,</span> <span class="nx">lily</span><span class="p">.</span><span class="nx">Country</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Her country is:  China</code></pre></td></tr></table>
</div>
</div>
<h6 id="成员的可见性">🐒成员的可见性</h6>

<p>成员的可见性是对外部package而言的，若某个变量对外部包可见，那么称这个变量是可导出的，在Go中，通过成员首字母大小写表明可见性，大写为可导出，小写不可导出，不可导出的成员只能在同一个包内访问</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">person</span>

<span class="kd">type</span> <span class="nx">Person</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Name</span>     <span class="kt">string</span>
	<span class="nx">Age</span>      <span class="kt">int</span>
	<span class="nx">loaction</span> <span class="kt">string</span>
<span class="p">}</span>
<span class="o">//</span> <span class="nx">Person结构体对外可见</span><span class="err">，</span><span class="nx">但是其内部的变量只有Name和Age成员对外可见</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

  <span class="nx">lily</span> <span class="o">:=</span> <span class="nx">Person</span><span class="p">{</span>
    <span class="nx">Name</span><span class="p">:</span> <span class="s">&#34;lily&#34;</span><span class="p">,</span>
    <span class="nx">Age</span><span class="p">:</span> <span class="mi">10</span><span class="p">,</span>
    <span class="nx">location</span><span class="p">:</span> <span class="s">&#34;China&#34;</span><span class="p">,</span><span class="c1">//这里会报错，外部的main包无法方位person包中Person结构体的不可见成员
</span><span class="c1"></span>  <span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<hr />

<h1 id="method">🐵method</h1>

<p>method 方法，附属给一个接收者的函数，接收者是某种类型的变量</p>

<h6 id="method的声明">🐒method的声明</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">接收者变量名称</span> <span class="nx">接收者变量类型</span><span class="p">)</span> <span class="nx">方法名</span><span class="p">()</span> <span class="nx">返回值</span> <span class="p">{</span>
  <span class="o">...</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="p">(</span><span class="nx">person</span> <span class="o">*</span><span class="nx">Person</span><span class="p">)</span> <span class="nf">Print</span><span class="p">(</span><span class="nx">name</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>
  <span class="k">return</span> <span class="kc">true</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="一些约束">🐒一些约束</h6>

<ul>
<li>只能为当前所在包内的类型定义方法</li>
<li>接收者可为值类型和指针类型，不可为接口类型和指针的指针类型</li>

<li><p>接收者为指针类型时，可用于修改其内容，接收者为值类型时不会改动其内容</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 接收者为指针类型
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">person</span> <span class="o">*</span><span class="nx">Person</span><span class="p">)</span> <span class="nf">Setname</span><span class="p">(</span><span class="nx">name</span> <span class="kt">string</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">person</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span>

<span class="nx">person</span><span class="p">.</span><span class="nf">Setname</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>

<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">person</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="c1">// 接收者为值类型
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">person</span> <span class="nx">Person</span><span class="p">)</span> <span class="nf">Print</span><span class="p">()</span> <span class="kt">bool</span> <span class="p">{</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">person</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">true</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div></li>
</ul>

<p><strong>同一个接收者的方法不可重名，若接收者是一个结构体，其方法名不可以和该结构体内的成员重名</strong></p>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--函数</title>
                <link>https://jjmeg.github.io/posts/golang-function/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-function/</guid>
                <pubDate>Fri, 13 Dec 2019 14:44:55 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「函数」</center>
<center>函数是将能够完成一定的功能的语句的包装集合，供外部调用。</center></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📚<a href="#函数结构">函数结构</a>

<ul>
<li>📖<a href="#参数及返回值缺省">参数及返回值缺省</a></li>
<li>📖<a href="#参数缺省">参数缺省</a></li>
<li>📖<a href="#返回值缺省">返回值缺省</a></li>
<li>📖<a href="#多返回值">多返回值</a></li>
<li>📖<a href="#多参数">多参数</a></li>
<li>📖<a href="#参数为引用类型">参数为引用类型</a></li>
</ul></li>
<li>📖<a href="#函数回调">函数回调</a></li>
<li>📖<a href="#匿名函数">匿名函数</a></li>
<li>📖<a href="#闭包">闭包</a></li>
</ul>

<hr />

<h1 id="函数结构">🐵函数结构</h1>

<p>包含函数名，参数和返回值三个部分，其中，参数及返回值可缺省</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="nx">函数名</span><span class="p">(</span> <span class="nx">参数1</span><span class="p">,</span> <span class="nx">参数2</span><span class="p">,</span> <span class="nx">参数3</span><span class="p">,</span> <span class="o">...</span><span class="p">)</span> <span class="p">(</span><span class="nx">返回值类型1</span><span class="p">,</span> <span class="nx">返回值类型2</span><span class="p">,</span> <span class="nx">返回值类型3</span><span class="p">){</span>

<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="参数及返回值缺省">🐒参数及返回值缺省</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="nf">HelloWorld</span><span class="p">(){</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Hello World!&#34;</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="参数缺省">🐒参数缺省</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 单返回值
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">HelloWorld</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
  <span class="k">return</span> <span class="s">&#34;Hello World!&#34;</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="返回值缺省">🐒返回值缺省</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="nf">HelloWorld</span><span class="p">(</span><span class="nx">hello</span> <span class="kt">string</span><span class="p">)</span> <span class="p">{</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">hello</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="多返回值">🐒多返回值</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="nf">HelloWorld</span><span class="p">()</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">bool</span><span class="p">){</span>
  <span class="k">return</span> <span class="s">&#34;Hello World!&#34;</span><span class="p">,</span> <span class="kc">true</span>
<span class="p">}</span>

<span class="c1">// 命名返回值
</span><span class="c1">// user及age均被初始化为默认值
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">HelloWorld</span><span class="p">()</span> <span class="p">(</span><span class="nx">user</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">age</span> <span class="kt">int</span><span class="p">){</span>
  <span class="nx">user</span> <span class="p">=</span> <span class="s">&#34;heihei&#34;</span>
  <span class="nx">age</span> <span class="p">=</span> <span class="mi">10</span>
  <span class="k">return</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="多参数">🐒多参数</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 参数个数确定
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">Sum</span><span class="p">(</span><span class="nx">num1</span><span class="p">,</span><span class="nx">num2</span><span class="p">,</span><span class="nx">num3</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">int</span><span class="p">{</span>
  <span class="k">return</span> <span class="nx">num1</span> <span class="o">+</span> <span class="nx">num2</span> <span class="o">+</span> <span class="nx">num3</span>
<span class="p">}</span>


<span class="c1">// 参数个数不确定，利用for range遍历参数
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">Sum</span><span class="p">(</span><span class="nx">nums</span> <span class="o">...</span><span class="kt">int</span><span class="p">)</span> <span class="kt">int</span><span class="p">{</span>
  <span class="nx">sum</span> <span class="o">:=</span> <span class="mi">0</span>

  <span class="k">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">value</span> <span class="p">=</span> <span class="k">range</span> <span class="nx">nums</span><span class="p">{</span>
    <span class="nx">sum</span> <span class="o">+=</span> <span class="nx">value</span>
  <span class="p">}</span>

  <span class="k">return</span> <span class="nx">sum</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="参数为引用类型">🐒参数为引用类型</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="kd">var</span> <span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">c</span> <span class="kt">int</span>
    <span class="nx">a</span> <span class="p">=</span> <span class="mi">1</span>
    <span class="nx">b</span> <span class="p">=</span> <span class="mi">2</span>
    <span class="nx">c</span> <span class="p">=</span> <span class="mi">3</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nf">Sum</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">a</span><span class="p">,</span><span class="o">&amp;</span><span class="nx">b</span><span class="p">,</span><span class="o">&amp;</span><span class="nx">c</span><span class="p">))</span>
<span class="p">}</span>

<span class="c1">//传入的参数为指针变量
</span><span class="c1"></span><span class="kd">func</span> <span class="nf">Sum</span><span class="p">(</span><span class="nx">num1</span><span class="p">,</span><span class="nx">num2</span><span class="p">,</span><span class="nx">num3</span> <span class="o">*</span><span class="kt">int</span><span class="p">)</span> <span class="kt">int</span><span class="p">{</span>
  <span class="k">return</span> <span class="o">*</span><span class="nx">num1</span> <span class="o">+</span> <span class="o">*</span><span class="nx">num2</span> <span class="o">+</span> <span class="o">*</span><span class="nx">num3</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="函数回调">🐵函数回调</h3>

<p>函数回调就是函数作为其他函数的参数，在其他函数内调用执行。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">ss</span> <span class="o">:=</span> <span class="s">&#34;golang&#34;</span>
  <span class="nx">ss1</span> <span class="o">:=</span> <span class="s">&#34;world&#34;</span>
  <span class="nf">sayhello</span><span class="p">(</span><span class="nx">ss</span><span class="p">,</span> <span class="nx">ss1</span><span class="p">,</span> <span class="nx">appenStr</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">appenStr</span><span class="p">(</span><span class="nx">prefix</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">suffix</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">prefix</span><span class="p">,</span> <span class="nx">name</span> <span class="p">,</span> <span class="nx">suffix</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">sayhello</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">suffix</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">f</span> <span class="kd">func</span> <span class="p">(</span><span class="kt">string</span><span class="p">,</span> <span class="kt">string</span><span class="p">,</span> <span class="kt">string</span><span class="p">))</span> <span class="p">{</span>
  <span class="nf">f</span> <span class="p">(</span><span class="s">&#34;hello&#34;</span><span class="p">,</span> <span class="nx">name</span><span class="p">,</span> <span class="nx">suffix</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">hello golang world</code></pre></td></tr></table>
</div>
</div>
<h3 id="匿名函数">🐵匿名函数</h3>

<p><strong>📎匿名函数是不需要定义函数名称的函数实现方式，例如下面这个函数就是一个匿名函数</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span><span class="p">(</span><span class="nx">num1</span><span class="p">,</span> <span class="nx">num2</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">int</span><span class="p">{</span>
  <span class="k">return</span> <span class="nx">num1</span> <span class="o">+</span> <span class="nx">num2</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>📎可以将匿名函数引用给其他变量，也可以把匿名函数设为其他函数的返回值</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

    <span class="kd">var</span> <span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">c</span> <span class="kt">int</span>
    <span class="nx">a</span> <span class="p">=</span> <span class="mi">9</span>
    <span class="nx">b</span> <span class="p">=</span> <span class="mi">2</span>
    <span class="nx">c</span> <span class="p">=</span> <span class="mi">1</span>
    <span class="nx">f</span> <span class="o">:=</span> <span class="nf">Anonymous</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">)</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nf">f</span><span class="p">(</span><span class="nx">c</span><span class="p">))</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">Anonymous</span><span class="p">(</span><span class="nx">num1</span><span class="p">,</span> <span class="nx">num2</span> <span class="kt">int</span><span class="p">)</span> <span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="kt">int</span><span class="p">){</span>
  <span class="nx">r</span> <span class="o">:=</span> <span class="kd">func</span><span class="p">(</span><span class="nx">num3</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">int</span><span class="p">{</span>
    <span class="k">return</span> <span class="p">(</span><span class="nx">num1</span> <span class="o">+</span> <span class="nx">num2</span> <span class="o">-</span> <span class="nx">num3</span><span class="p">)</span>
  <span class="p">}</span>
  <span class="k">return</span> <span class="nx">r</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p>以上程序完成 num1 + num2 - num3 = 9 + 2 -1 = 10</p>

<p><strong>📎匿名函数的传参</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

    <span class="nx">ss</span> <span class="o">:=</span> <span class="s">&#34;hello world!&#34;</span>

    <span class="kd">func</span><span class="p">(</span><span class="nx">hello</span> <span class="kt">string</span><span class="p">){</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">hello</span><span class="p">)</span>
    <span class="p">}(</span><span class="nx">ss</span><span class="p">)</span>
    <span class="c1">// 后面的括号中的ss作为参数传到匿名函数中
</span><span class="c1"></span><span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">hello world!</code></pre></td></tr></table>
</div>
</div>
<h3 id="闭包">🐵闭包</h3>

<p>闭包能够读取其他函数内部变量的函数。</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

    <span class="nx">ss</span> <span class="o">:=</span> <span class="s">&#34;world&#34;</span>

    <span class="nf">hello</span><span class="p">(</span><span class="nx">ss</span><span class="p">)</span>
<span class="p">}</span>

<span class="kd">func</span> <span class="nf">hello</span><span class="p">(</span><span class="nx">ss</span> <span class="kt">string</span><span class="p">)</span>  <span class="p">{</span>
  <span class="nx">text</span> <span class="o">:=</span> <span class="s">&#34;hello&#34;</span> <span class="o">+</span> <span class="s">&#34; &#34;</span> <span class="o">+</span> <span class="nx">ss</span>

  <span class="nx">f</span> <span class="o">:=</span> <span class="kd">func</span> <span class="p">()</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">text</span><span class="p">)</span>
  <span class="p">}</span>

  <span class="nf">f</span><span class="p">()</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">hello world</code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--流程控制</title>
                <link>https://jjmeg.github.io/posts/golang-process-control/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-process-control/</guid>
                <pubDate>Fri, 13 Dec 2019 14:21:15 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「流程控制」</center>
<p style="text-indent:2em">开发人员控制程序执行路径的方式，常见的流程控制语句包括条件判断、循环、跳转，以实现程序的执行顺序控制。</p></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📖<a href="#if/else分支">if/else分支</a></li>
<li>📖<a href="#switch分支">switch分支</a></li>
<li>📖<a href="#select分支">select分支</a></li>
<li>📖<a href="#for循环">for循环</a></li>
<li>📖<a href="#goto跳转">goto跳转</a></li>
</ul>

<hr />

<h6 id="if-else分支">🐵if/else分支</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="k">if</span> <span class="nx">条件</span> <span class="p">{</span>
  <span class="o">...</span>
  <span class="o">...</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
  <span class="o">...</span>
  <span class="o">...</span>
<span class="p">}</span>

<span class="c1">//条件可写在同一行，但是不同条件间要加上;隔开
</span><span class="c1"></span><span class="k">if</span> <span class="nx">条件1</span><span class="p">;</span> <span class="nx">条件2</span> <span class="p">..</span> <span class="p">{</span>
  <span class="o">...</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">personAge</span> <span class="o">:=</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span>
  	<span class="s">&#34;Amy&#34;</span> <span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
  	<span class="s">&#34;Daming&#34;</span> <span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
  	<span class="s">&#34;Lily&#34;</span> <span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
  <span class="p">}</span>

  <span class="k">if</span> <span class="nx">value</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Amy&#34;</span><span class="p">];</span> <span class="nx">ok</span> <span class="o">==</span> <span class="kc">true</span><span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Amy’s value is &#34;</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
  <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Amy is not here.&#34;</span><span class="p">)</span>
  <span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell"> Amy’s value is <span class="m">1</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="switch分支">🐵switch分支</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="k">switch</span> <span class="nx">变量</span><span class="p">:{</span>
  <span class="k">case</span> <span class="nx">条件1</span><span class="p">:</span>
    <span class="o">...</span>
  <span class="k">case</span> <span class="nx">条件2</span><span class="p">:</span>
    <span class="o">...</span>
  <span class="k">case</span> <span class="nx">条件3</span><span class="p">:</span>
    <span class="o">...</span>
  <span class="k">case</span> <span class="nx">条件4</span><span class="p">:</span>
    <span class="o">...</span>
  <span class="k">case</span> <span class="nx">条件5</span><span class="p">,</span> <span class="nx">条件6</span><span class="p">,</span> <span class="nx">条件7</span><span class="p">,</span> <span class="nx">条件8</span><span class="p">:</span><span class="c1">//多个条件选项并列用,隔开
</span><span class="c1"></span>    <span class="o">...</span>
  <span class="k">default</span><span class="p">:</span><span class="c1">//上述条件不满足时进入此逻辑
</span><span class="c1"></span>    <span class="o">...</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">number</span> <span class="o">:=</span> <span class="mi">3</span>
  <span class="k">switch</span> <span class="nx">number</span><span class="p">{</span>
  <span class="k">case</span> <span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">:</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;number是基础类&#34;</span><span class="p">)</span>
    <span class="k">case</span> <span class="mi">3</span><span class="p">:</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;number是特别类&#34;</span><span class="p">)</span>
    <span class="k">default</span><span class="p">:</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;number为其他类&#34;</span><span class="p">)</span>
  <span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>注意:</strong></p>

<ul>
<li>与其他语言不同，Go中的switch，在执行完一个case后默认退出switch，不会再做其他的case判断</li>

<li><p>fallthrough：用于继续执行下一个case</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

<span class="k">switch</span> <span class="nx">number</span> <span class="o">:=</span> <span class="mi">6</span> <span class="p">;{</span>
  <span class="k">case</span> <span class="nx">number</span> <span class="p">&gt;</span> <span class="mi">0</span><span class="p">:</span>
      <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;number大于0&#34;</span><span class="p">)</span>
      <span class="k">fallthrough</span>
  <span class="k">case</span> <span class="nx">number</span> <span class="p">&lt;</span> <span class="mi">10</span><span class="p">:</span>
      <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;number小于10&#34;</span><span class="p">)</span>
      <span class="k">fallthrough</span>
  <span class="k">case</span> <span class="nx">number</span> <span class="p">&gt;</span> <span class="mi">5</span><span class="p">:</span>
      <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;number大于5&#34;</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">number大于0
number小于10
number大于5</code></pre></td></tr></table>
</div>
</div></li>
</ul>

<h6 id="select分支">🐵select分支</h6>

<p>select监听IO操作，常用于监听channel，可阅读 <a href="/posts/golang-channel.md">Golang系列教程--Channel</a></p>

<h6 id="for循环">🐵for循环</h6>

<p>Go语言中没有while语句，用for来描述循环</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-fallback" data-lang="fallback">for 初始值 ; 满足范围; 操作{
  ...
}</code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
    <span class="k">for</span> <span class="nx">k</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">k</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">k</span><span class="o">++</span><span class="p">{</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;k is :%d\n&#34;</span><span class="p">,</span> <span class="nx">k</span><span class="p">)</span>
    <span class="p">}</span>

    <span class="c1">// 多个变量控制，用,隔开
</span><span class="c1"></span>    <span class="k">for</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="o">:=</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&gt;=</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="nx">j</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="p">=</span> <span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nx">j</span><span class="o">+</span><span class="mi">1</span> <span class="p">{</span>
		<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%d * %d = %d\n&#34;</span><span class="p">,</span> <span class="nx">j</span><span class="p">,</span> <span class="nx">i</span><span class="p">,</span> <span class="nx">j</span><span class="o">*</span><span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">k is :1
k is :2
k is :3
k is :4
k is :5
k is :6
k is :7
k is :8
k is :9
k is :10

<span class="c1"># 多个变量控制输出结果</span>
<span class="m">1</span> * <span class="nv">10</span> <span class="o">=</span> <span class="m">10</span>
<span class="m">2</span> * <span class="nv">9</span> <span class="o">=</span> <span class="m">18</span>
<span class="m">3</span> * <span class="nv">8</span> <span class="o">=</span> <span class="m">24</span>
<span class="m">4</span> * <span class="nv">7</span> <span class="o">=</span> <span class="m">28</span>
<span class="m">5</span> * <span class="nv">6</span> <span class="o">=</span> <span class="m">30</span>
<span class="m">6</span> * <span class="nv">5</span> <span class="o">=</span> <span class="m">30</span>
<span class="m">7</span> * <span class="nv">4</span> <span class="o">=</span> <span class="m">28</span>
<span class="m">8</span> * <span class="nv">3</span> <span class="o">=</span> <span class="m">24</span>
<span class="m">9</span> * <span class="nv">2</span> <span class="o">=</span> <span class="m">18</span>
<span class="m">10</span> * <span class="nv">1</span> <span class="o">=</span> <span class="m">10</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>支持continue和break</strong></p>

<p>break用于终止当前所在的for循环，continue表明本次循环中不执行continue后续的语句，直接进入下一次循环</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

    <span class="c1">// continue完成了只输出k&gt;5的取值
</span><span class="c1"></span>    <span class="k">for</span> <span class="nx">k</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">k</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">k</span><span class="o">++</span><span class="p">{</span>
        <span class="k">if</span> <span class="nx">k</span> <span class="o">&lt;=</span> <span class="mi">5</span><span class="p">{</span>
            <span class="k">continue</span>
        <span class="p">}</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;k is :%d\n&#34;</span><span class="p">,</span> <span class="nx">k</span><span class="p">)</span>
    <span class="p">}</span>


    <span class="c1">// break让i=10时退出for循环
</span><span class="c1"></span>    <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="p">;</span> <span class="nx">i</span> <span class="p">=</span> <span class="nx">i</span><span class="o">+</span><span class="mi">1</span> <span class="p">{</span>
        <span class="k">if</span> <span class="nx">i</span> <span class="o">==</span> <span class="mi">10</span><span class="p">{</span>
            <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34; is :%d\n&#34;</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span>
            <span class="k">break</span>
        <span class="p">}</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;i is :%d\n&#34;</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>

<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">本例中continue的效果
k is :6
k is :7
k is :8
k is :9
k is :10

本例中break的效果
i is :1
i is :2
i is :3
i is :4
i is :5
i is :6
i is :7
i is :8
i is :9
i is :10</code></pre></td></tr></table>
</div>
</div>
<h6 id="goto跳转">🐵goto跳转</h6>

<p>goto使得程序直接到指定行执行，不过不建议常用，goto容易造成程序流程混乱</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;=</span> <span class="mi">10</span> <span class="p">;</span> <span class="nx">i</span> <span class="p">=</span> <span class="nx">i</span><span class="o">+</span><span class="mi">1</span> <span class="p">{</span>
      <span class="k">if</span> <span class="nx">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
          <span class="k">goto</span> <span class="nx">Find</span>
      <span class="p">}</span>
      <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;i is :%d\n&#34;</span><span class="p">,</span> <span class="nx">i</span><span class="p">)</span>
	<span class="p">}</span>

  <span class="nx">Find</span><span class="p">:</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;偶数出现&#34;</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">i is :1
偶数出现</code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--Map</title>
                <link>https://jjmeg.github.io/posts/golang-map/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-map/</guid>
                <pubDate>Thu, 12 Dec 2019 14:14:35 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<p><center>「Map」</center>
<p style="text-indent:2em">键值对的无序集合，key唯一，根据key可快速查找数据，底层用哈希表实现。</p></p>

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📖<a href="#map的初始化">map的初始化</a></li>
<li>📖<a href="#map插入元素">map插入元素</a></li>
<li>📖<a href="#map删除元素">map删除元素</a></li>
<li>📖<a href="#map访问元素">map访问元素</a></li>
<li>📖<a href="#map的遍历">map的遍历</a></li>
</ul>

<h6 id="map的初始化">🐵map的初始化</h6>

<p>使用<code>make</code>关键字，<code>make(map[T]T)</code></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="c1">// 创建一个key为string，value为int类型的map
</span><span class="c1"></span><span class="nx">map1</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">)</span>
<span class="c1">// 复合map，key为string，value为一个map
</span><span class="c1"></span><span class="nx">map2</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="map插入元素">🐵map插入元素</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span>	<span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// 声明map
</span><span class="c1"></span>	<span class="kd">var</span> <span class="nx">personAge</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span>
  <span class="c1">// 初始化map
</span><span class="c1"></span>	<span class="nx">personAge</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">)</span>

  <span class="c1">// 插入数据
</span><span class="c1"></span>	<span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Amy&#34;</span><span class="p">]</span> <span class="p">=</span> <span class="mi">1</span>
	<span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Daming&#34;</span><span class="p">]</span> <span class="p">=</span> <span class="mi">2</span>

	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Create a map&#34;</span><span class="p">:</span> <span class="nx">personAge</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Create a map : map<span class="o">[</span>Daming:2 Amy:1<span class="o">]</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="map删除元素">🐵map删除元素</h6>

<p>使用内置函数<code>delete(map,key)</code></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// 声明map
</span><span class="c1"></span>  <span class="kd">var</span> <span class="nx">personAge</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span>
  <span class="c1">// 初始化map
</span><span class="c1"></span>  <span class="nx">personAge</span> <span class="p">=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">)</span>

  <span class="c1">// 插入数据
</span><span class="c1"></span>	<span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Amy&#34;</span><span class="p">]</span> <span class="p">=</span> <span class="mi">1</span>
	<span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Daming&#34;</span><span class="p">]</span> <span class="p">=</span> <span class="mi">2</span>

	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Create a map :&#34;</span><span class="p">,</span><span class="nx">personAge</span><span class="p">)</span>

  <span class="c1">// 删除一个数据
</span><span class="c1"></span>	<span class="nb">delete</span><span class="p">(</span><span class="nx">personAge</span><span class="p">,</span> <span class="s">&#34;Amy&#34;</span><span class="p">)</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;delete Amy :&#34;</span><span class="p">,</span><span class="nx">personAge</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Create a map : map<span class="o">[</span>Daming:2 amy:1<span class="o">]</span>
Delete Amy : map<span class="o">[</span>Daming:2<span class="o">]</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="map访问元素">🐵map访问元素</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">personAge</span> <span class="o">:=</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span>
  	<span class="s">&#34;Amy&#34;</span> <span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
  	<span class="s">&#34;Daming&#34;</span> <span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
  	<span class="s">&#34;Lily&#34;</span> <span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
  <span class="p">}</span>

  <span class="c1">// 1. 通过key的内容直接获取：不存在则返回值类型的0值，例如map[string]string，不存在的返回&#34;&#34;
</span><span class="c1"></span>	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Get Jimmy :&#34;</span><span class="p">,</span><span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Jimmy&#34;</span><span class="p">])</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Get Amy :&#34;</span><span class="p">,</span><span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Amy&#34;</span><span class="p">])</span>

  <span class="c1">// 2. personAge[&#34;Jimmy&#34;]返回两个参数
</span><span class="c1"></span>  <span class="nx">value</span> <span class="p">,</span><span class="nx">ok</span> <span class="o">:=</span> <span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Jimmy&#34;</span><span class="p">]</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="s">&#34;Jimmy exists ? &#34;</span><span class="p">,</span><span class="nx">ok</span><span class="p">)</span>

  <span class="nx">value</span> <span class="p">,</span><span class="nx">ok</span> <span class="p">=</span> <span class="nx">personAge</span><span class="p">[</span><span class="s">&#34;Amy&#34;</span><span class="p">]</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Amy exists ? %v the value is : %d&#34;</span><span class="p">,</span> <span class="nx">ok</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div>
<p><strong>在访问元素时，第一个参数是访问的元素的值，第二个参数为元素是否存在，存在则是true，不存在为false，此外，不存在的元素的返回值是元素取值的默认0值。</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">Get Jimmy : <span class="m">0</span>
Get Amy : <span class="m">1</span>
Jimmy exists ?  <span class="nb">false</span>
Amy exists ? <span class="nb">true</span> the value is :1</code></pre></td></tr></table>
</div>
</div>
<h6 id="map的遍历">🐵map的遍历</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="nx">personAge</span> <span class="o">:=</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span>
  	<span class="s">&#34;Amy&#34;</span> <span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
  	<span class="s">&#34;Daming&#34;</span> <span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
  	<span class="s">&#34;Lily&#34;</span> <span class="p">:</span> <span class="mi">3</span><span class="p">,</span>
  <span class="p">}</span>

  <span class="k">for</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">value</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">personAge</span> <span class="p">{</span>
    <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;key: %s, value: %d\n&#34;</span><span class="p">,</span> <span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
  <span class="p">}</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">key: Amy, value: <span class="m">1</span>
key: Daming, value: <span class="m">2</span>
key: Lily, value: <span class="m">3</span></code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--数组和切片</title>
                <link>https://jjmeg.github.io/posts/golang-array-and-slice/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-array-and-slice/</guid>
                <pubDate>Thu, 12 Dec 2019 11:30:21 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li><p>📚<a href="#数组">数组</a></p>

<ul>
<li>📖<a href="#声明方式">声明方式</a></li>
<li>📖<a href="#遍历方式">遍历方式</a></li>
</ul></li>

<li><p>📚<a href="#切片">切片</a></p>

<ul>
<li>📖<a href="#一个切片例子">一个切片例子</a></li>
<li>📖<a href="#容量和长度">容量和长度</a></li>
<li>📖<a href="#切片的创建">切片的创建</a></li>
</ul></li>

<li><p>📚<a href="#数组和切片区别">数组和切片区别</a></p></li>
</ul>

<h3 id="数组">🐵数组</h3>

<ul>
<li>相同元素的固定容量的集合，一旦被声明，容量固定，若插入新数据超出数组范围将报错误</li>
<li>数组是值类型</li>
</ul>

<h6 id="声明方式">🐒声明方式</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go">  <span class="kn">package</span> <span class="nx">main</span>

  <span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

  <span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
    <span class="c1">//1
</span><span class="c1"></span>    <span class="kd">var</span> <span class="nx">num1</span> <span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="kt">int</span>

    <span class="c1">//2
</span><span class="c1"></span>    <span class="kd">var</span> <span class="nx">num2</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="kt">int</span>
    <span class="nx">num2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">=</span> <span class="mi">1</span>
    <span class="nx">num2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">=</span> <span class="mi">2</span>
    <span class="nx">num2</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="p">=</span> <span class="mi">3</span>

    <span class="c1">//2
</span><span class="c1"></span>    <span class="nx">num3</span> <span class="o">:=</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">}</span>

  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%v\n%v\n%v\n&#34;</span><span class="p">,</span><span class="nx">num1</span><span class="p">,</span><span class="nx">num2</span><span class="p">,</span><span class="nx">num3</span><span class="p">)</span>
  <span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">  <span class="o">[</span><span class="m">0</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span> 0<span class="o">]</span>
  <span class="o">[</span><span class="m">1</span> <span class="m">2</span> 3<span class="o">]</span>
  <span class="o">[</span><span class="m">1</span> <span class="m">2</span> 3<span class="o">]</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="遍历方式">🐒遍历方式</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go">  <span class="kn">package</span> <span class="nx">main</span>

  <span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

  <span class="kd">func</span> <span class="nf">main</span><span class="p">(){</span>
    <span class="kd">var</span> <span class="nx">nums</span> <span class="p">=</span> <span class="p">[</span><span class="mi">8</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">}</span>

    <span class="c1">//内置函数len取长度，通过数组索引做遍历
</span><span class="c1"></span>    <span class="k">for</span> <span class="nx">i</span> <span class="o">:=</span> <span class="mi">0</span><span class="p">;</span><span class="nx">i</span><span class="p">&lt;</span><span class="nb">len</span><span class="p">(</span><span class="nx">nums</span><span class="p">);</span><span class="nx">i</span><span class="o">++</span><span class="p">{</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%d\n&#34;</span><span class="p">,</span><span class="nx">nums</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span>
    <span class="p">}</span>

    <span class="c1">//使用range遍历，i为下标，v为该下标存储的数值
</span><span class="c1"></span>    <span class="k">for</span> <span class="nx">i</span><span class="p">,</span><span class="nx">v</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">nums</span><span class="p">{</span>
        <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;Index:%d\tvalue:%d\n&#34;</span><span class="p">,</span><span class="nx">i</span><span class="p">,</span><span class="nx">v</span><span class="p">)</span>
    <span class="p">}</span>
  <span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">  len方式遍历结果：
    <span class="m">1</span>
    <span class="m">2</span>
    <span class="m">3</span>
    <span class="m">4</span>
    <span class="m">5</span>
    <span class="m">6</span>
    <span class="m">7</span>
    <span class="m">8</span>
  range方式遍历结果：
    Index:0	value:1
    Index:1	value:2
    Index:2	value:3
    Index:3	value:4
    Index:4	value:5
    Index:5	value:6
    Index:6	value:7
    Index:7	value:8</code></pre></td></tr></table>
</div>
</div>
<hr />

<h3 id="切片">🐵切片</h3>

<ul>
<li>是数组的部分，引用数组的一段内容，实际不存储任何值</li>

<li><p>对切片的修改即是对引用的数组的修改</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="nx">nums</span> <span class="o">:=</span> <span class="p">[</span><span class="mi">8</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">}</span>
<span class="kd">var</span> <span class="nx">s</span> <span class="p">[]</span><span class="kt">int</span> <span class="p">=</span> <span class="nx">nums</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span></code></pre></td></tr></table>
</div>
</div></li>
</ul>

<h6 id="一个切片例子">🐒一个切片例子</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// 新建了一个int数组，将数组的引用分配给一个切片
</span><span class="c1"></span>	<span class="kd">var</span> <span class="nx">array</span> <span class="p">=</span> <span class="p">[</span><span class="o">...</span><span class="p">]</span><span class="kt">int</span><span class="p">{</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">}</span>
  <span class="kd">var</span> <span class="nx">nums</span> <span class="p">=</span> <span class="nx">array</span><span class="p">[</span><span class="mi">3</span><span class="p">:</span><span class="mi">5</span><span class="p">]</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;length of nums is:%d, the capacity is %d\n &#34;</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="nx">nums</span><span class="p">),</span> <span class="nb">cap</span><span class="p">(</span><span class="nx">nums</span><span class="p">))</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">length of nums is:2, the capacity is <span class="m">5</span></code></pre></td></tr></table>
</div>
</div>
<h6 id="容量和长度">🐒容量和长度</h6>

<ul>
<li>长度：表示当前切片包含的元素个数</li>
<li>容量：表示切片可包含的最多元素个数</li>
<li>上述例子中，nums指向array数组从第3到第5的部分，那么当前nums元素个数为2，nums是从第3个开始的，最多可以到第8个，那么切片的容量最多为5</li>
</ul>

<h6 id="切片的创建">🐒切片的创建</h6>

<ul>
<li>新建数组，指向数组的部分，如上述例子中</li>

<li><p>make：<code>make([]T, len, cap)</code></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="nx">i</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span></code></pre></td></tr></table>
</div>
</div></li>
</ul>

<hr />

<h3 id="数组和切片区别">🐵数组和切片区别</h3>

<table>
<thead>
<tr>
<th align="center">数组</th>
<th align="center">切片</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">值类型</td>
<td align="center">引用类型</td>
</tr>

<tr>
<td align="center">存储数据</td>
<td align="center">不存储数据</td>
</tr>

<tr>
<td align="center">长度不可变</td>
<td align="center">长度可变，但有最大容量</td>
</tr>
</tbody>
</table>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--基础结构与类型</title>
                <link>https://jjmeg.github.io/posts/golang-basic-struct-and-types/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-basic-struct-and-types/</guid>
                <pubDate>Wed, 11 Dec 2019 18:00:47 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li>📚<a href="#基础类型">基础类型</a>

<ul>
<li>📖<a href="#布尔型">布尔型</a></li>
<li>📖<a href="#数值类型">数值类型</a></li>
<li>📖<a href="#字符串">字符串</a></li>
<li>📖<a href="#基础类型默认取值">基础类型默认取值</a></li>
<li>📖<a href="#错误类型">错误类型</a></li>
</ul></li>
<li>📚<a href="#变量">变量</a>

<ul>
<li>📖<a href="#指针变量">指针变量</a></li>
<li>📖<a href="#指向指针的指针">指向指针的指针</a></li>
<li>📖<a href="#变量命名">变量命名</a></li>
<li>📖<a href="#变量声明程序例子">变量声明程序例子</a></li>
<li>📖<a href="#变量生命周期">变量生命周期</a></li>
<li>📖<a href="#值类型和引用类型">值类型和引用类型</a></li>
</ul></li>
<li>📚<a href="#常量">常量</a>

<ul>
<li>📖<a href="#常量定义">常量定义</a></li>
<li>📖<a href="#常量模拟枚举">常量模拟枚举</a></li>
</ul></li>
</ul>

<hr />

<h1 id="基础类型">🐵基础类型</h1>

<h3 id="布尔型">布尔型</h3>

<table>
<thead>
<tr>
<th align="center">类型</th>
<th align="center">内存占用大小</th>
<th align="center">取值范围</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">bool</td>
<td align="center">1字节</td>
<td align="center">true和false</td>
</tr>
</tbody>
</table>

<h3 id="数值类型">数值类型</h3>

<h6 id="1-无符号整型">🐒1.无符号整型</h6>

<table>
<thead>
<tr>
<th align="center">类型</th>
<th align="center">内存占用大小</th>
<th align="center">取值范围</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">uint8又称byte</td>
<td align="center">1字节</td>
<td align="center">0~255</td>
</tr>

<tr>
<td align="center">uint16</td>
<td align="center">2字节</td>
<td align="center">0~65535</td>
</tr>

<tr>
<td align="center">uint32</td>
<td align="center">4字节</td>
<td align="center">0~4294967295</td>
</tr>

<tr>
<td align="center">uint64</td>
<td align="center">8字节</td>
<td align="center">0~18446744073709551615</td>
</tr>
</tbody>
</table>

<h6 id="2-有符号整型">🐒2.有符号整型</h6>

<table>
<thead>
<tr>
<th align="center">类型</th>
<th align="center">内存占用大小</th>
<th align="center">取值范围</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">int8</td>
<td align="center">1字节</td>
<td align="center">-128~127</td>
</tr>

<tr>
<td align="center">int16</td>
<td align="center">2字节</td>
<td align="center">-32768~32767</td>
</tr>

<tr>
<td align="center">int32</td>
<td align="center">4字节</td>
<td align="center">-2147483648~2147483647</td>
</tr>

<tr>
<td align="center">int64</td>
<td align="center">8字节</td>
<td align="center">-9223372036854775808~9223372036854775807</td>
</tr>
</tbody>
</table>

<p><strong>注：Golang中的int在未明确指定位数时，默认为int32</strong></p>

<h6 id="3-浮点型">🐒3.浮点型</h6>

<table>
<thead>
<tr>
<th align="center">类型</th>
<th align="center">内存占用大小</th>
<th align="center">取值范围</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">float32</td>
<td align="center">4字节</td>
<td align="center">1.4e-45~3.4e38</td>
</tr>

<tr>
<td align="center">float64</td>
<td align="center">8字节</td>
<td align="center">4.9e-324~1.8e308</td>
</tr>
</tbody>
</table>

<h3 id="字符串">字符串</h3>

<p>Go中的字符串由字节组成，不可变类型，使用UTF-8编码</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="nx">name</span> <span class="p">=</span> <span class="s">&#34;hello&#34;</span></code></pre></td></tr></table>
</div>
</div>
<p>常用处理字符串的包
- strconv：提供了多种数值与字符串转化的函数
- strings：提供多种字符串处理的方法</p>

<h3 id="基础类型默认取值">基础类型默认取值</h3>

<table>
<thead>
<tr>
<th align="center">布尔型</th>
<th align="center">数值类型</th>
<th align="center">字符串</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">false</td>
<td align="center">0</td>
<td align="center">&quot;&quot;</td>
</tr>
</tbody>
</table>

<h3 id="错误类型">错误类型</h3>

<ul>
<li><p>Go内置的接口，Go中的errors包实现了Error()函数，当然也可以自定义实现错误类型</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">type</span> <span class="kt">error</span> <span class="kd">interface</span> <span class="p">{</span>
<span class="nf">Error</span><span class="p">()</span> <span class="kt">string</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">TestError</span> <span class="kd">struct</span> <span class="p">{</span>
	<span class="nx">Msg</span> <span class="kt">string</span>
<span class="p">}</span>

<span class="c1">// 实现了Error接口
</span><span class="c1"></span><span class="kd">func</span> <span class="p">(</span><span class="nx">e</span> <span class="nx">TestError</span><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <span class="kt">string</span> <span class="p">{</span>
	<span class="k">return</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprintf</span><span class="p">(</span><span class="s">&#34;%v&#34;</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nx">Msg</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div></li>
</ul>

<hr />

<h1 id="变量">🐵变量</h1>

<ul>
<li>声明形式：

<ul>
<li><code>var [变量名] [变量类型]</code>: <code>var name string</code></li>
<li><code>new</code>: <code>b := new(bool)</code>  <code>new</code>会分配被置零的存储，在此<code>b</code>的值为<code>false</code></li>
<li><code>make</code>: <code>make(chan bool)</code> 新建<code>map</code>、<code>slice</code>、<code>channel</code>类型的数据</li>
</ul></li>
<li>注意：

<ul>
<li>关键字不能作为变量名，例如const/var/import等</li>
<li>首字母大写则该变量可导出</li>
<li>函数内声明的为局部变量，全局变量则在import语句后作声明</li>
</ul></li>
<li>初始化：

<ul>
<li>未手动赋值，变量被初始化成默认值，<code>int:0</code>，<code>string:&quot;&quot;</code>，<code>bool:false</code></li>
</ul></li>
</ul>

<h3 id="指针变量">指针变量</h3>

<h6 id="1-和-的区别">🐒1.* 和 &amp; 的区别</h6>

<table>
<thead>
<tr>
<th align="center">&amp;</th>
<th align="center">*</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">取地址符号</td>
<td align="center">指针运算符</td>
</tr>

<tr>
<td align="center">对变量取地址</td>
<td align="center">一个变量是指针类型<br/>指针变量所处的存储单元<br/></td>
</tr>

<tr>
<td align="center">a = *&amp;a</td>
<td align="center">a = <em>&amp;</em>&amp;<em>&amp;</em>&amp;*&amp;a</td>
</tr>
</tbody>
</table>

<p><strong>*&amp;可以相互抵消，&amp;*不可以抵消</strong></p>

<h3 id="指向指针的指针">指向指针的指针</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-go" data-lang="go"><span class="nx">i</span> <span class="p">=</span> <span class="mi">1</span>
<span class="kd">var</span> <span class="nx">ptr</span> <span class="o">*</span><span class="kt">int</span> <span class="p">=</span> <span class="o">&amp;</span><span class="nx">i</span>
<span class="kd">var</span> <span class="nx">pptr</span> <span class="o">**</span><span class="kt">int</span> <span class="p">=</span> <span class="o">&amp;</span><span class="nx">ptr</span></code></pre></td></tr></table>
</div>
</div>
<table>
<thead>
<tr>
<th align="center">ptr</th>
<th align="center">pptr</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">ptr是一个指针变量</br>ptr的类型是*int</td>
<td align="center">pptr是一个指针变量</br>pptr的类型是**int，也是&amp;ptr</td>
</tr>

<tr>
<td align="center">*ptr = 1</td>
<td align="center">**pptr = 1</td>
</tr>
</tbody>
</table>

<h3 id="变量命名">变量命名</h3>

<p>推荐阅读：驼峰命名法</p>

<h3 id="变量声明程序例子">变量声明程序例子</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">qq</span> <span class="kt">int</span>
<span class="kd">type</span> <span class="nx">pp</span> <span class="kt">float32</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
 <span class="c1">// 用var声明变量，用 = 赋值，Go会自动检测变量的类型
</span><span class="c1"></span> <span class="kd">var</span> <span class="nx">name</span> <span class="p">=</span> <span class="s">&#34;haha&#34;</span>
 <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span>

 <span class="c1">// 省略var关键字，用 := 初始化，Go会自动检测变量的类型
</span><span class="c1"></span> <span class="nx">name1</span> <span class="o">:=</span> <span class="s">&#34;hahaha&#34;</span>
 <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">name1</span><span class="p">)</span>

 <span class="kd">var</span> <span class="nx">a</span><span class="p">,</span> <span class="nx">b</span> <span class="p">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span>
 <span class="kd">var</span> <span class="nx">c</span><span class="p">,</span> <span class="nx">d</span> <span class="p">=</span> <span class="mi">3</span><span class="p">,</span> <span class="s">&#34;ha&#34;</span>
 <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">,</span> <span class="nx">c</span><span class="p">,</span> <span class="nx">d</span><span class="p">)</span>

 <span class="c1">//默认初始化为0
</span><span class="c1"></span> <span class="kd">var</span> <span class="nx">a1</span> <span class="nx">qq</span>
 <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">a1</span><span class="p">)</span>
 <span class="kd">var</span> <span class="nx">s1</span> <span class="nx">pp</span>
 <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">s1</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-shell" data-lang="shell">haha
hahaha
<span class="m">1</span> <span class="m">2</span> <span class="m">3</span> ha
<span class="m">0</span>
<span class="m">0</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="变量生命周期">变量生命周期</h3>

<ul>
<li>包级别变量：整个程序执行过程</li>
<li>局部变量：每次执行声明时建立一个实体，一直生存到它不可访问，函数的参数和返回值都是局部变量，不可访问后，其实体所占的内存空间将被收回</li>
</ul>

<h3 id="值类型和引用类型">值类型和引用类型</h3>

<table>
<thead>
<tr>
<th align="center">值类型</th>
<th align="center">引用类型</th>
</tr>
</thead>

<tbody>
<tr>
<td align="center">基本数据类型</br>数组</br>结构体</td>
<td align="center">指针</br>slice</br>map</br>channel</br>interface</td>
</tr>

<tr>
<td align="center">变量直接存储值，内存通常在栈中分配</td>
<td align="center">变量存储的值是一个地址，这个地址对应的空间 才真正存储数据，内存通常在堆上分配，当没有任何变量引用这个地址时，会被GC回收</td>
</tr>
</tbody>
</table>

<hr />

<h1 id="常量">🐵常量</h1>

<ul>
<li>常量是无法改变的，在声明时就已确定好具体的值，通常包含基本数据类型和字符串类型</li>
<li>用关键字const修饰</li>
<li>常量可作枚举</li>
</ul>

<h3 id="常量定义">常量定义</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="nx">pacakge</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">const</span><span class="p">(</span>
  <span class="nx">Country</span> <span class="p">=</span> <span class="s">&#34;China&#34;</span>
  <span class="nx">Weight</span> <span class="p">=</span> <span class="mi">10</span>
<span class="p">)</span></code></pre></td></tr></table>
</div>
</div>
<h3 id="常量模拟枚举">常量模拟枚举</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kn">package</span> <span class="nx">main</span>

<span class="kn">import</span> <span class="s">&#34;fmt&#34;</span>

<span class="kd">type</span> <span class="nx">Weight</span> <span class="kt">int</span>

<span class="kd">const</span> <span class="p">(</span>
	<span class="nx">State1</span> <span class="nx">Weight</span> <span class="p">=</span> <span class="kc">iota</span> <span class="c1">//开始生成枚举常量，State1为0
</span><span class="c1"></span>	<span class="nx">State2</span>
	<span class="nx">State3</span>
	<span class="nx">State4</span>
	<span class="nx">State5</span>
<span class="p">)</span>

<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
	<span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;%d, %d, %d, %d, %d\n&#34;</span><span class="p">,</span><span class="nx">State1</span><span class="p">,</span> <span class="nx">State2</span><span class="p">,</span> <span class="nx">State3</span><span class="p">,</span> <span class="nx">State4</span><span class="p">,</span> <span class="nx">State5</span><span class="p">)</span>

  <span class="kd">var</span> <span class="nx">level</span> <span class="nx">Weight</span> <span class="p">=</span> <span class="nx">State5</span>
  <span class="nx">fmt</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">&#34;level is: %d\n&#34;</span><span class="p">,</span><span class="nx">level</span><span class="p">)</span>
<span class="p">}</span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-bash" data-lang="bash">0, 1, 2, 3, <span class="m">4</span>
level is: <span class="m">4</span></code></pre></td></tr></table>
</div>
</div>]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Golang系列教程--基础概念</title>
                <link>https://jjmeg.github.io/posts/golang-basic-concetps/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/golang-basic-concetps/</guid>
                <pubDate>Tue, 10 Dec 2019 13:47:14 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[

<h1 id="本文内容">📜本文内容</h1>

<ul>
<li><p>👉<a href="#包的概念package">包的概念package</a></p></li>

<li><p>👉 <a href="#Go程序的结构">Go程序的结构</a></p></li>

<li><p>👉 <a href="#Go的执行">Go的执行</a></p></li>

<li><p>👉 <a href="#可见性规则">可见性规则</a></p></li>

<li><p>👉 <a href="#Go的编译过程">Go的编译过程</a></p></li>
</ul>

<hr />

<h3 id="包的概念package">👽包的概念package</h3>

<ul>
<li>每个go文件仅属于一个包，一个包可以多个go文件</li>
<li>所有包名为小写字母</li>
<li>包编译完为pack1.a，包的依赖关系决定程序构建顺序，包为编译单元，每个目录只包含一个包</li>
<li><strong>包内文件或重新编译有修改，引用该包的其他程序也要重新编译</strong></li>
<li>包名也可作为命名空间使用，eg：pack1.Id, pack2.Id</li>
<li>包名自命名，eg：import fm &quot;fmt&quot;  fm.Println(&quot;hello&quot;)</li>
<li>导入未使用的包时会报错，导入包的语句后可以定义全局变量，在本包内都可访问</li>
<li>包编译完为pack1.a</li>
</ul>

<h3 id="go程序的结构">👽Go程序的结构</h3>

<ol>
<li>import包</li>
<li>声明常量、全局变量、类型定义</li>

<li><p>init()若含有，则包首先执行init()且只执行一次,<strong>任何文件可以包含任意多个init()，按照声明的顺序执行</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre class="chroma"><code class="language-Go" data-lang="Go"><span class="kd">func</span> <span class="nf">init</span><span class="p">()</span> <span class="p">{</span> <span class="cm">/*........*/</span> <span class="p">}</span></code></pre></td></tr></table>
</div>
</div></li>

<li><p>若是main包，此处写main函数</p></li>

<li><p>其他函数</p></li>
</ol>

<h3 id="go的执行">👽Go的执行</h3>

<ol>
<li>按顺序导入所有被main包引用的包，每个包执行以下流程：

<ul>
<li>若该包又引入了其他包，从1继续，但每个包只能导入一次</li>
<li>相反的顺序初始化变量、常量，有init()执行init()</li>
</ul></li>
<li>回到main执行一样的初始化和init()过程</li>
</ol>

<h3 id="可见性规则">👽可见性规则</h3>

<ul>
<li>类似java中的public、private关键字</li>
<li>标识符以大写字母开头，外部包即可访问，eg：struct Person{}，Person对象即可被外部包访问(导出/public)</li>
<li>以小写字母，即private，仅包内可见可用</li>
<li>在导入一个外部包后，只能够访问该包中导出的对象</li>
</ul>

<h3 id="go的编译过程">👽Go的编译过程</h3>

<ul>
<li>run: compile and run Go program

<ul>
<li>go run执行完后生成归档文件和可执行文件</li>
<li>go run -a强制编译所有代码</li>
</ul></li>
<li>build: compile packages and dependencies

<ul>
<li>go build在目录中执行，将产生与目录同名的可执行文件</li>
<li>若编译库源码文件，build完不产生任何结果，build只检查库源码文件的有效性，不输出任何文件</li>
<li>go build 后不接路径则默认编译的包的路径为当前目录</li>
<li>-o 指定输出名称</li>
<li>过程与go run相似，但最后会将生成的可执行文件移动(不是复制，go run产生的exe不存在了)到目录下</li>
</ul></li>
<li>install: download and install packages and dependencies

<ul>
<li>编译并安装指定的代码包、依赖包</li>
<li>go install将build命令生成的可执行文件移动到GOPATH/bin下</li>
<li>过程与go build类似，但最后安装编译后的结果文件到指定目录</li>
<li>命令后可接路径</li>
<li>不支持对库源码文件的安装</li>
</ul></li>
<li>get: download and install packages and dependencies

<ul>
<li>go get从远程仓库下载</li>
<li>-d只做下载操作不安装</li>
</ul></li>
</ul>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/golang/">golang</category>
                                
                            
                                
                                
                                
                                    <category domain="https://jjmeg.github.io/tags/go%E5%9F%BA%E7%A1%80/">go基础</category>
                                
                            
                        
                    
                
            </item>
        
            <item>
                <title>Hello World</title>
                <link>https://jjmeg.github.io/posts/hello-world/</link>
                <guid isPermaLink="true">https://jjmeg.github.io/posts/hello-world/</guid>
                <pubDate>Mon, 09 Dec 2019 18:14:09 +0800</pubDate>
                
                    <author>jjmeg.he@gmail.com (JJMeg)</author>
                
                <copyright>[CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)</copyright>
                
                    <description><![CDATA[<p>This is a <del>test</del> article.</p>

<p><br />
「What」</p>

<p>首次尝试博客是在2017年 👉 基于 <a href="https://hexo.io/" target="_blank">Hexo</a> 👉 <a href="https://github.com/JJMeg/JJMeg0.github.io" target="_blank">JJMeg0</a></p>

<p><del>学业繁忙</del>（拖拉机本机💅），遂落灰...</p>

<p><del>社（毕）会（业）人（了）</del>（互联网🐶）开始营业🕘...</p>

<p><br />
「Why」</p>

<p>云计算行业萌新，近半年接触 <a href="https://golang.org/" target="_blank">Go</a>，听闻 <a href="https://gohugo.io/" target="_blank">Hugo</a> 构建编译速度，（搓手）尝试⚡，体验 hin👌。</p>

<p><br />
「How」</p>

<p>🔍主题选用👻 <a href="https://io-oi.me/" target="_blank">一休儿</a> 👻超级优秀的💖 <a href="https://github.com/reuixiy/hugo-theme-meme" target="_blank">meme</a> 💖，</p>

<p>📒评论插件为 <a href="https://utteranc.es/" target="_blank">utteranc</a>，</p>

<p>✒ 编辑器为 <a href="https://atom.io/" target="_blank">Atom</a> ✒，写作由 <a href="https://www.markdown.cn/" target="_blank">Markdown</a> 支持。</p>

<p><br />
<br />
<center>Enjoy it!</center></p>
]]></description>
                
                
                
                
                
                    
                        
                    
                        
                    
                
            </item>
        
    </channel>
</rss>