<repo_name>weitrue/weitrue.github.io<file_sep>/2021/10/28/memo/index.html

  <script type="text/javascript">
    (function () {
      var dayStr = '12/13';
      if (/^\d{1,2}\/\d{1,2}$/.test(dayStr)) {
        dayStr = new Date().getFullYear() + '/' + dayStr;
      }
      if (!/^\d{4}\/\d{1,2}\/\d{1,2}$/.test(dayStr)) {
        return ;
      }
      var day = new Date(dayStr);
      var now = new Date();
      var isMemorialDay = now.getFullYear() === day.getFullYear() && now.getMonth() === day.getMonth() && now.getDate() === day.getDate();
      if (isMemorialDay) {
        if (document.all) {
          window.style = 'html {     -webkit-filter: grayscale(100%); /* webkit */     -moz-filter: grayscale(100%); /* firefox */     -ms-filter: grayscale(100%); /* ie9 */     -o-filter: grayscale(100%); /* opera */     filter: grayscale(100%);     filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); filter:gray; /* ie9- */   }';
          document.createStyleSheet('javascript:style');
        } else {
          var style = document.createElement('style');
          style.type = 'text/css';
          style.innerHTML = 'html {     -webkit-filter: grayscale(100%); /* webkit */     -moz-filter: grayscale(100%); /* firefox */     -ms-filter: grayscale(100%); /* ie9 */     -o-filter: grayscale(100%); /* opera */     filter: grayscale(100%);     filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); filter:gray; /* ie9- */   }';
          document.getElementsByTagName('HEAD').item(0).appendChild(style);
        }
      }
    })();
  </script>
  

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/images/img/logo.png">
  <link rel="icon" href="/images/img/logo.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="<NAME>">
  <meta name="keywords" content="">
  
    <meta name="description" content="生活工作备忘录与待办事项。">
<meta property="og:type" content="article">
<meta property="og:title" content="【备忘录】工作与学习">
<meta property="og:url" content="https://weitrue.github.io/2021/10/28/memo/index.html">
<meta property="og:site_name" content="weitrable">
<meta property="og:description" content="生活工作备忘录与待办事项。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://weitrue.github.io/images/memo/index.jpg">
<meta property="article:published_time" content="2021-10-28T02:53:39.733Z">
<meta property="article:modified_time" content="2021-10-28T02:53:39.733Z">
<meta property="article:author" content="<NAME>">
<meta property="article:tag" content="备忘录">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://weitrue.github.io/images/memo/index.jpg">
  
  
    <meta name="referrer" content="no-referrer-when-downgrade">
  
  
  <title>【备忘录】工作与学习 - weitrable</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />

  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"weitrue.github.io","root":"/","version":"1.9.4","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":1},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="weitrable" type="application/atom+xml">
</head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 60vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>WeiTrable</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/book/">
                <i class="iconfont icon-books"></i>
                <span>混沌书栈</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/bookstack/">
                <i class="iconfont icon-plan"></i>
                <span>混沌日记</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                <span>友链</span>
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/images/img/banner.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="【备忘录】工作与学习"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        Pony W
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2021-10-28 10:53" pubdate>
          2021年10月28日 上午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          <!-- compatible with older versions-->
          9.1k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          <!-- compatible with older versions-->
          29 分钟
        
      </span>
    

    
    
      
        <span id="busuanzi_container_page_pv" style="display: none">
          <i class="iconfont icon-eye" aria-hidden="true"></i>
          <span id="busuanzi_value_page_pv"></span> 次
        </span>
        
      
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">【备忘录】工作与学习</h1>
            
            
              <div class="markdown-body">
                
                <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><blockquote>
<p>生活工作备忘录与待办事项。 <span id="more"></span></p>
</blockquote>
<h3 id="google浏览器插件">Google浏览器插件</h3>
<div class="note note-success">
            <p><span class="label label-danger">Tampermonkey</span></p><p>Tampermonkey（油猴）是一款针对于浏览器运行脚本的插件，一款必装的浏览器插件神器。</p><p>可以去脚本市场 <a target="_blank" rel="noopener" href="https://greasyfork.org/zh-CN/scripts">greasyfork</a> 去下载自己想要的插件，非常实用。</p><p>这里推荐两个常用的脚本：</p><ul><li><a target="_blank" rel="noopener" href="https://greasyfork.org/zh-CN/scripts/14178-ac-baidu-重定向优化百度搜狗谷歌搜索-去广告-favicon-双列">AC-baidu 重定向优化百度搜狗谷歌搜索；</a></li><li>破解 VIP 会员视频集合。</li></ul><p><a target="_blank" rel="noopener" href="https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo?utm_source=chrome-ntp-icon">下载地址</a></p>
          </div>
<div class="note note-info">
            <p><span class="label label-danger">Wappalyzer</span></p><p>可以发现网站上使用的技术。 它检测内容管理系统，电子商务平台，Web 框架，服务器软件，分析工具等。</p><p><a target="_blank" rel="noopener" href="https://chrome.google.com/webstore/detail/wappalyzer/gppongmhjkpfnbhagpmjfkannfbllamg?utm_source=chrome-ntp-icon">下载地址</a></p>
          </div>
<div class="note note-success">
            <p><span class="label label-danger">OneTab</span></p><p>当有太多的标签页时，单击OneTab图标，将所有标签页转换成一个列表。再次访问这些标签页时，可以单独或全部恢复它们。</p><p><a target="_blank" rel="noopener" href="https://chrome.google.com/webstore/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall?utm_source=chrome-ntp-icon">下载地址</a></p>
          </div>
<div class="note note-info">
            <p><span class="label label-danger">Adblock Plus</span></p><p>Adblock Plus 广告拦截器可有效的拦截所有网页上的所有类型的广告。</p><p><a target="_blank" rel="noopener" href="https://chrome.google.com/webstore/detail/adblock-plus-free-ad-bloc/cfhdojbkjhnklbpkdaibdccddilifddb?utm_source=chrome-ntp-icon">下载地址</a></p>
          </div>
<div class="note note-success">
            <p><span class="label label-danger">Octotree</span></p><p>这款神器可以GitHub平台代码在最左侧显示出树状目录，非常人性化的设计，你可以点击左侧目录切换到项目中的任意一个位置中去。</p><p><a target="_blank" rel="noopener" href="https://chrome.google.com/webstore/detail/octotree-github-code-tree/bkhaagjahfmjljalopjnoealnfndnagc">下载地址</a></p>
          </div>
<h3 id="hexo插件">Hexo插件</h3>
<div class="note note-primary">
            <p><span class="label label-danger">hexo-admonition</span></p><p>​ Hexo 内容辅助插件，支持将类似 <a target="_blank" rel="noopener" href="https://docutils.sourceforge.io/docs/ref/rst/directives.html">reStructuredText</a> 的警告提示块添加到 Markdown 文档中。</p><p>​ <a target="_blank" rel="noopener" href="https://github.com/lxl80/hexo-admonition">安装</a></p>
          </div>
<div class="note note-warning">
            <p><span class="label label-danger">hexo-butterfly-charts</span></p><p>​ 将 hexo poats、类别和标签的统计数据呈现到图表中。</p><p>​ <a target="_blank" rel="noopener" href="https://github.com/kuole-o/hexo-butterfly-charts">安装</a></p>
          </div>
<div class="note note-primary">
            <p><span class="label label-danger">hexo-deployer-rss3</span></p><p>​ Hexo 的 RSS3 部署插件。</p><p><a target="_blank" rel="noopener" href="https://github.com/NaturalSelectionLabs/hexo-deployer-rss3">安装</a></p>
          </div>
<div class="note note-warning">
            <p><span class="label label-danger">hexo-math</span></p><p>​ 通过标签插件在 Hexo 帖子/页面中嵌入 KaTeX 和 MathJax。</p><p>​ <a target="_blank" rel="noopener" href="https://github.com/hexojs/hexo-math">安装</a></p><p>数学公式 <span class="math display">\[E=mc^2\]</span></p>
          </div>
<div class="note note-primary">
            <p><span class="label label-danger">hexo-referenc</span></p><p>​ 在 Hexo 博客文章中支持 Markdown 脚注和 Wiki 样式工具提示参考的插件<sup id="fnref:1"><a href="#fn:1" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label=" [测试](https://en.wikipedia.org/wiki/Markdown)">[1]</span></a></sup>。</p><p>​ <a target="_blank" rel="noopener" href="https://github.com/kchen0x/hexo-reference">安装</a></p><p>流程图</p><pre><code class=" mermaid">classDiagram
Class01 &lt;|-- AveryLongClass : Cool
Class03 *-- Class04
Class05 o-- Class06
Class07 .. Class08
Class09 --&gt; C2 : Where am i?
Class09 --* C3
Class09 --|&gt; Class07
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 &lt;--&gt; C2: Cool label
</code></pre>
          </div>
<div class="note note-warning">
            <p><span class="label label-danger">hexo-simple-mindmap</span></p><p>基于百度脑图的开源库 kityminder开发的hexo思维导图插件。</p><p><a target="_blank" rel="noopener" href="https://github.com/HunterXuan/hexo-simple-mindmap">安装</a></p><p>思维导图</p><blockquote class="pullquote mindmap mindmap-md"><ul><li>知识图谱<ul><li>Golang</li><li>Python</li><li>Java<ul><li>JVM</li></ul></li></ul></li><li>消息队列<ul><li>Kafka</li><li>Pulsar</li></ul></li></ul></blockquote>
          </div>
<div class="note note-primary">
            <p><span class="label label-danger">hexo-spoiler</span></p><p>折叠博客内容,实现根据需要显示/隐藏博客内容<sup id="fnref:2"><a href="#fn:2" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="[Hexo Fluid 代码折叠](https://wty-yy.github.io/posts/44830/)">[2]</span></a></sup>。</p><p><a target="_blank" rel="noopener" href="https://github.com/unnamed42/hexo-spoiler">安装</a></p>
          </div>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        内容
    </div>
    <div class="spoiler-content">
        <p>内容</p>

    </div>
</div>
<h3 id="npm与node环境更新">npm与node环境更新</h3>
<h4 id="更新记录">更新记录</h4>
<p><code>npm install -g npm</code>更新npm失败</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs shell">/usr/local/bin/npm -&gt; /usr/local/lib/node_modules/npm/bin/npm-cli.js<br>/usr/local/bin/npx -&gt; /usr/local/lib/node_modules/npm/bin/npx-cli.js<br>npm WARN notsup Unsupported engine for npm@8.2.0: wanted: &#123;&quot;node&quot;:&quot;^12.13.0 || ^14.15.0 || &gt;=16&quot;&#125; (current: &#123;&quot;node&quot;:&quot;13.9.0&quot;,&quot;npm&quot;:&quot;6.14.8&quot;&#125;)<br>npm WARN notsup Not compatible with your version of node/npm: npm@8.2.0<br><br>+ npm@8.2.0<br>added 67 packages from 17 contributors, removed 287 packages and updated 147 packages in 4.402s<br></code></pre></td></tr></table></figure>
<p>发现需要依赖的node版本不对</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta">#</span><span class="bash"> 输入命令 npm install -g n</span><br>npm does not support Node.js v13.9.0<br>You should probably upgrade to a newer version of node as we<br>can&#x27;t make any promises that npm will work with this version.<br>You can find the latest version at https://nodejs.org/<br></code></pre></td></tr></table></figure>
<p>因此单独更新node</p>
<h4 id="更新node">更新node</h4>
<h5 id="查看当前node版本">查看当前node版本</h5>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs shell">node –v<br>internal/modules/cjs/loader.js:983<br>  throw err;<br>  ^<br><br>Error: Cannot find module &#x27;/Users/wangpeng/Projects/MyProject/weitrue.github.io/–v&#x27;<br>    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:980:15)<br>    at Function.Module._load (internal/modules/cjs/loader.js:862:27)<br>    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)<br>    at internal/main/run_main_module.js:17:47 &#123;<br>  code: &#x27;MODULE_NOT_FOUND&#x27;,<br>  requireStack: []<br>&#125;<br></code></pre></td></tr></table></figure>
<p>直接报错</p>
<h4 id="安装n模块">安装n模块</h4>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install -g n<br></code></pre></td></tr></table></figure>
<h4 id="升级到指定版本最新版本">升级到指定版本/最新版本</h4>
<p><code>n v@version</code></p>
<p>可以告诉管理器，安装最新的稳定版本</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs shell">n stable<br>  installing : node-v16.13.1<br>       mkdir : /usr/local/n/versions/node/16.13.1<br></code></pre></td></tr></table></figure>
<p>安装稳定版本</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs shell">n v16.13.1<br>  installing : node-v16.13.1<br>       mkdir : /usr/local/n/versions/node/16.13.1<br>mkdir: /usr/local/n/versions/node/16.13.1: Permission denied<br><br>  Error: sudo required (or change ownership, or define N_PREFIX)<br></code></pre></td></tr></table></figure>
<p>需要授权</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs shell">sudo n v16.13.1<br>Password:<br>  installing : node-v16.13.1<br>       mkdir : /usr/local/n/versions/node/16.13.1<br>       fetch : https://nodejs.org/dist/v16.13.1/node-v16.13.1-darwin-x64.tar.xz<br>   installed : v16.13.1 (with npm 8.1.2)<br></code></pre></td></tr></table></figure>
<p>检查是否安装成功</p>
<figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs crmsh"><span class="hljs-keyword">node</span> <span class="hljs-title">-v</span><br>v16.<span class="hljs-number">13.1</span><br></code></pre></td></tr></table></figure>
<h4 id="更新npm">更新npm</h4>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install -g npm<br>npm ERR! code EACCES<br>npm ERR! syscall rename<br>npm ERR! path /usr/local/lib/node_modules/npm<br>npm ERR! dest /usr/local/lib/node_modules/.npm-i9nnxROI<br>npm ERR! errno -13<br>npm ERR! Error: EACCES: permission denied, rename &#x27;/usr/local/lib/node_modules/npm&#x27; -&gt; &#x27;/usr/local/lib/node_modules/.npm-i9nnxROI&#x27;<br>npm ERR!  [Error: EACCES: permission denied, rename &#x27;/usr/local/lib/node_modules/npm&#x27; -&gt; &#x27;/usr/local/lib/node_modules/.npm-i9nnxROI&#x27;] &#123;<br>npm ERR!   errno: -13,<br>npm ERR!   code: &#x27;EACCES&#x27;,<br>npm ERR!   syscall: &#x27;rename&#x27;,<br>npm ERR!   path: &#x27;/usr/local/lib/node_modules/npm&#x27;,<br>npm ERR!   dest: &#x27;/usr/local/lib/node_modules/.npm-i9nnxROI&#x27;<br>npm ERR! &#125;<br>npm ERR!<br>npm ERR! The operation was rejected by your operating system.<br>npm ERR! It is likely you do not have the permissions to access this file as the current user<br>npm ERR!<br>npm ERR! If you believe this might be a permissions issue, please double-check the<br>npm ERR! permissions of the file and its containing directories, or try running<br>npm ERR! the command again as root/Administrator.<br><br>npm ERR! A complete log of this run can be found in:<br>npm ERR!     /Users/wangpeng/.npm/_logs/2021-12-07T02_12_59_256Z-debug.log<br></code></pre></td></tr></table></figure>
<p>需要授权</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install npm -g<br><br>changed 14 packages in 2s<br><br>10 packages are looking for funding<br>  run `npm fund` for details<br></code></pre></td></tr></table></figure>
<h4 id="更新后带来问题">更新后带来问题</h4>
<h5 id="fluid主题hero-g报错">fluid主题<code>hero g</code>报错</h5>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><code class="hljs shell">exo g<br>INFO  Validating config<br>INFO  Start processing<br>INFO<br>------------------------------------------------<br>|                                              |<br>|     ________  __            _        __      |<br>|    |_   __  |[  |          (_)      |  ]     |<br>|      | |_ \_| | | __   _   __   .--.| |      |<br>|      |  _|    | |[  | | | [  |/ /&#x27;`\&#x27; |      |<br>|     _| |_     | | | \_/ |, | || \__/  |      |<br>|    |_____|   [___]&#x27;.__.&#x27;_/[___]&#x27;.__.;__]     |<br>|                                              |<br>|       Thank you for using Fluid theme !      |<br>|    Docs: https://hexo.fluid-dev.com/docs/    |<br>|                                              |<br>------------------------------------------------<br><br>FATAL &#123;<br>  err: Error: Function yaml.safeLoad is removed in js-yaml 4. Use yaml.load instead, which is now safe by default.<br>      at Object.safeLoad (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/js-yaml/index.js:10:11)<br>      at module.exports (/Users/wangpeng/Projects/MyProject/weitrue.github.io/themes/fluid/scripts/events/lib/merge-configs.js:32:24)<br>      at Hexo.&lt;anonymous&gt; (/Users/wangpeng/Projects/MyProject/weitrue.github.io/themes/fluid/scripts/events/index.js:7:33)<br>      at Hexo.emit (node:events:402:35)<br>      at Hexo._generate (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/hexo/lib/hexo/index.js:452:10)<br>      at /Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/hexo/lib/hexo/index.js:324:24<br>      at tryCatcher (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/util.js:16:23)<br>      at Promise._settlePromiseFromHandler (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:547:31)<br>      at Promise._settlePromise (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:604:18)<br>      at Promise._settlePromise0 (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:649:10)<br>      at Promise._settlePromises (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:729:18)<br>      at Promise._fulfill (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:673:18)<br>      at Promise._resolveCallback (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:466:57)<br>      at Promise._settlePromiseFromHandler (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:559:17)<br>      at Promise._settlePromise (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:604:18)<br>      at Promise._settlePromise0 (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:649:10)<br>      at Promise._settlePromises (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:729:18)<br>      at Promise._fulfill (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:673:18)<br>      at PromiseArray._resolve (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise_array.js:127:19)<br>      at PromiseArray._promiseFulfilled (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise_array.js:145:14)<br>      at Promise._settlePromise (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:609:26)<br>      at Promise._settlePromise0 (/Users/wangpeng/Projects/MyProject/weitrue.github.io/node_modules/bluebird/js/release/promise.js:649:10)<br>&#125; Something&#x27;s wrong. Maybe you can find the solution here: %s https://hexo.io/docs/troubleshooting.html<br></code></pre></td></tr></table></figure>
<p><a target="_blank" rel="noopener" href="https://github.com/fluid-dev/hexo-theme-fluid/issues/446">解决办法</a></p>
<h5 id="npm与node后引发问题-循环依赖">npm与node后引发问题-循环依赖</h5>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta">$</span><span class="bash"> hexo s</span><br>INFO  Validating config<br>INFO  Start processing<br>INFO<br>------------------------------------------------<br>|                                              |<br>|     ________  __            _        __      |<br>|    |_   __  |[  |          (_)      |  ]     |<br>|      | |_ \_| | | __   _   __   .--.| |      |<br>|      |  _|    | |[  | | | [  |/ /&#x27;`\&#x27; |      |<br>|     _| |_     | | | \_/ |, | || \__/  |      |<br>|    |_____|   [___]&#x27;.__.&#x27;_/[___]&#x27;.__.;__]     |<br>|                                              |<br>|       Thank you for using Fluid theme !      |<br>|    Docs: https://hexo.fluid-dev.com/docs/    |<br>|                                              |<br>------------------------------------------------<br><br>INFO  Hexo is running at http://localhost:4000 . Press Ctrl+C to stop.<br>(node:87224) Warning: Accessing non-existent property &#x27;lineno&#x27; of module exports inside circular dependency<br>(Use `node --trace-warnings ...` to show where the warning was created)<br>(node:87224) Warning: Accessing non-existent property &#x27;column&#x27; of module exports inside circular dependency<br>(node:87224) Warning: Accessing non-existent property &#x27;filename&#x27; of module exports inside circular dependency<br>(node:87224) Warning: Accessing non-existent property &#x27;lineno&#x27; of module exports inside circular dependency<br>(node:87224) Warning: Accessing non-existent property &#x27;column&#x27; of module exports inside circular dependency<br>(node:87224) Warning: Accessing non-existent property &#x27;filename&#x27; of module exports inside circular dependency<br></code></pre></td></tr></table></figure>
<p>google后，发现一位博主<a target="_blank" rel="noopener" href="https://www.haoyizebo.com/posts/710984d0/">修改nib@1.1.2依赖</a>，尝试后不成功。</p>
<p>于是，采用主流办法<a target="_blank" rel="noopener" href="https://github.com/hexojs/hexo/issues/4257">node.js降级</a></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs shell"> node -v<br>v12.22.7<br></code></pre></td></tr></table></figure>
<p>后来发现<strong>具体原因</strong>是由于 <a target="_blank" rel="noopener" href="https://github.com/stylus/stylus">stylus</a> 导致的，stylus 在 0.54.8 版本修复了这个问题（见 pr <a target="_blank" rel="noopener" href="https://github.com/stylus/stylus/pull/2538">#2538</a> ）,所以重新装一下 <code>hexo-renderer-stylus</code> 就可以了<sup id="fnref:3"><a href="#fn:3" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="[解决 Hexo 在使用 Node.js 14 时的 Accessing non-existent property &#39;xxx&#39; of module exports inside circular dependency 问题](https://www.haoyizebo.com/posts/710984d0/)
">[3]</span></a></sup>.</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install hexo-renderer-stylus --save<br></code></pre></td></tr></table></figure>
<div id="footnotes">
<hr>
<div id="footnotelist">
<ol style="list-style: none; padding-left: 0; margin-left: 40px">
<li id="fn:1">
<span style="display: inline-block; vertical-align: top; padding-right: 10px; margin-left: -40px">1.</span><span style="display: inline-block; vertical-align: top; margin-left: 10px;"><a target="_blank" rel="noopener" href="https://en.wikipedia.org/wiki/Markdown">测试</a><a href="#fnref:1" rev="footnote"> ↩︎</a></span>
</li>
<li id="fn:2">
<span style="display: inline-block; vertical-align: top; padding-right: 10px; margin-left: -40px">2.</span><span style="display: inline-block; vertical-align: top; margin-left: 10px;"><a target="_blank" rel="noopener" href="https://wty-yy.github.io/posts/44830/">Hexo Fluid 代码折叠</a><a href="#fnref:2" rev="footnote"> ↩︎</a></span>
</li>
<li id="fn:3">
<span style="display: inline-block; vertical-align: top; padding-right: 10px; margin-left: -40px">3.</span><span style="display: inline-block; vertical-align: top; margin-left: 10px;"><a target="_blank" rel="noopener" href="https://www.haoyizebo.com/posts/710984d0/">解决 Hexo 在使用 Node.js 14 时的 Accessing non-existent property 'xxx' of module exports inside circular dependency 问题</a><a href="#fnref:3" rev="footnote"> ↩︎</a></span>
</li>
</ol>
</div>
</div>
<script type="text&#x2F;javascript" src="https://cdn.jsdelivr.net/npm/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://cdn.jsdelivr.net/npm/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.7.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.7.0/dist/mindmap.min.css"><link rel="stylesheet" href="/css/spoiler.css" type="text/css"><script src="/js/spoiler.js" type="text/javascript" async></script>
                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/%E5%A4%87%E5%BF%98%E5%BD%95/" class="category-chain-item">备忘录</a>
  
  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/%E5%A4%87%E5%BF%98%E5%BD%95/">#备忘录</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>【备忘录】工作与学习</div>
      <div>https://weitrue.github.io/2021/10/28/memo/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div><NAME></div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2021年10月28日</div>
        </div>
      
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/11/29/chain/" title="【区块链与元宇宙】学习笔记">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">【区块链与元宇宙】学习笔记</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/10/27/prometheus-blackbox/" title="【Prometheus】Blackbox黑盒测试">
                        <span class="hidden-mobile">【Prometheus】Blackbox黑盒测试</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  


  
  





  <script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/mermaid@8/dist/mermaid.min.js', function() {
    mermaid.initialize({"theme":"default"});

    Fluid.events.registerRefreshCallback(function() {
      if ('mermaid' in window) {
        mermaid.init();
      }
    });
  });
</script>






    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="#" target="_blank" rel="nofollow noopener"><span>Wei</span></a> <i class="iconfont icon-love"></i> <a href="#" target="_blank" rel="nofollow noopener"><span>Trable</span></a> <div style="font-size: 0.85rem"> <span id="timeDate">载入天数...</span> <span id="times">载入时分秒...</span> <script src="/cus_js/duration.js"></script> </div> 
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="busuanzi_container_site_pv" style="display: none">
        总访问量 
        <span id="busuanzi_value_site_pv"></span>
         次
      </span>
    
    
      <span id="busuanzi_container_site_uv" style="display: none">
        总访客数 
        <span id="busuanzi_value_site_uv"></span>
         人
      </span>
    
    
  
</div>

  
  
    <!-- 备案信息 ICP for China -->
    <div class="beian">
  <span>
    <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
      杭ICP证123456号
    </a>
  </span>
  
    
      <span>
        <a
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=12345678"
          rel="nofollow noopener"
          class="beian-police"
          target="_blank"
        >
          
            <span style="visibility: hidden; width: 0">|</span>
            <img src="/images/img/police_beian.png" srcset="/img/loading.gif" lazyload alt="police-icon"/>
          
          <span>杭公网安备12345678号</span>
        </a>
      </span>
    
  
</div>

  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  
      <script>
        if (!window.MathJax) {
          window.MathJax = {
            tex    : {
              inlineMath: { '[+]': [['$', '$']] }
            },
            loader : {
              load: ['ui/lazy']
            },
            options: {
              renderActions: {
                insertedScript: [200, () => {
                  document.querySelectorAll('mjx-container').forEach(node => {
                    let target = node.parentNode;
                    if (target.nodeName.toLowerCase() === 'li') {
                      target.parentNode.classList.add('has-jax');
                    }
                  });
                }, '', false]
              }
            }
          };
        } else {
          MathJax.startup.document.state(0);
          MathJax.texReset();
          MathJax.typeset();
          MathJax.typesetPromise();
        }

        Fluid.events.registerRefreshCallback(function() {
          if ('MathJax' in window && MathJax.startup.document && typeof MathJax.startup.document.state === 'function') {
            MathJax.startup.document.state(0);
            MathJax.texReset();
            MathJax.typeset();
            MathJax.typesetPromise();
          }
        });
      </script>
    

  <script  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" ></script>

  <script  src="/js/local-search.js" ></script>

  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
<file_sep>/js/musicshow.js
!(function() {
  function show() {
    //直接把音乐框隐藏
	$("#music_div").attr("style","display:none;");
    //滚动条事件
	$(window).scroll(function(){
		//获取滚动条的滑动距离
		var scroH = $(this).scrollTop();
		//滚动条的滑动距离大于120，就显示，反之就隐藏
		if(scroH >= 120){
			$("#music_div").attr("style","display:block;position:fixed;bottom:0px;left:30px;");
		}else if(scroH < 120){
			$("#music_div").attr("style","display:none;");
		}
	})
  }
  show();
})();
<file_sep>/2021/02/07/golang/index.html

  <script type="text/javascript">
    (function () {
      var dayStr = '12/13';
      if (/^\d{1,2}\/\d{1,2}$/.test(dayStr)) {
        dayStr = new Date().getFullYear() + '/' + dayStr;
      }
      if (!/^\d{4}\/\d{1,2}\/\d{1,2}$/.test(dayStr)) {
        return ;
      }
      var day = new Date(dayStr);
      var now = new Date();
      var isMemorialDay = now.getFullYear() === day.getFullYear() && now.getMonth() === day.getMonth() && now.getDate() === day.getDate();
      if (isMemorialDay) {
        if (document.all) {
          window.style = 'html {     -webkit-filter: grayscale(100%); /* webkit */     -moz-filter: grayscale(100%); /* firefox */     -ms-filter: grayscale(100%); /* ie9 */     -o-filter: grayscale(100%); /* opera */     filter: grayscale(100%);     filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); filter:gray; /* ie9- */   }';
          document.createStyleSheet('javascript:style');
        } else {
          var style = document.createElement('style');
          style.type = 'text/css';
          style.innerHTML = 'html {     -webkit-filter: grayscale(100%); /* webkit */     -moz-filter: grayscale(100%); /* firefox */     -ms-filter: grayscale(100%); /* ie9 */     -o-filter: grayscale(100%); /* opera */     filter: grayscale(100%);     filter:progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); filter:gray; /* ie9- */   }';
          document.getElementsByTagName('HEAD').item(0).appendChild(style);
        }
      }
    })();
  </script>
  

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/images/img/logo.png">
  <link rel="icon" href="/images/img/logo.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="<NAME>">
  <meta name="keywords" content="">
  
    <meta name="description" content="&quot;Go has indeed become the language of cloud infrastructure&quot; - Rob Pike interview">
<meta property="og:type" content="article">
<meta property="og:title" content="【Go】学习笔记">
<meta property="og:url" content="https://weitrue.github.io/2021/02/07/golang/index.html">
<meta property="og:site_name" content="weitrable">
<meta property="og:description" content="&quot;Go has indeed become the language of cloud infrastructure&quot; - Rob Pike interview">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://weitrue.github.io/images/golang/index.jpg">
<meta property="article:published_time" content="2021-02-07T01:55:11.025Z">
<meta property="article:modified_time" content="2021-02-07T01:55:11.025Z">
<meta property="article:author" content="<NAME>">
<meta property="article:tag" content="Go">
<meta property="article:tag" content="ADT">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://weitrue.github.io/images/golang/index.jpg">
  
  
    <meta name="referrer" content="no-referrer-when-downgrade">
  
  
  <title>【Go】学习笔记 - weitrable</title>

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@4/github-markdown.min.css" />

  <link  rel="stylesheet" href="/lib/hint/hint.min.css" />

  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_kmeydafke9r.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"weitrue.github.io","root":"/","version":"1.9.4","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"right","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":1},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 5.4.0"><link rel="alternate" href="/atom.xml" title="weitrable" type="application/atom+xml">
</head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 60vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>WeiTrable</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                <span>首页</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                <span>归档</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                <span>分类</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/book/">
                <i class="iconfont icon-books"></i>
                <span>混沌书栈</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/bookstack/">
                <i class="iconfont icon-plan"></i>
                <span>混沌日记</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                <span>标签</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                <span>关于</span>
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/links/">
                <i class="iconfont icon-link-fill"></i>
                <span>友链</span>
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              <i class="iconfont icon-search"></i>
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">
              <i class="iconfont icon-dark" id="color-toggle-icon"></i>
            </a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/images/img/banner.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="【Go】学习笔记"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        <NAME>
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2021-02-07 09:55" pubdate>
          2021年2月7日 上午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          <!-- compatible with older versions-->
          71k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          <!-- compatible with older versions-->
          223 分钟
        
      </span>
    

    
    
      
        <span id="busuanzi_container_page_pv" style="display: none">
          <i class="iconfont icon-eye" aria-hidden="true"></i>
          <span id="busuanzi_value_page_pv"></span> 次
        </span>
        
      
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">【Go】学习笔记</h1>
            
            
              <div class="markdown-body">
                
                <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><blockquote>
<p>"Go has indeed become the language of cloud infrastructure" - <NAME> interview<span id="more"></span></p>
</blockquote>
<h3 id="变量">变量</h3>
<h4 id="var与">var与:=</h4>
<ul>
<li>:=方式较为简洁，但只能在函数内使用该方式，var方式没有这个限制，var方式定义在汉书外的变量属于包内部的变量</li>
<li>函数中以:=方式定义变量为主</li>
</ul>
<h4 id="内建变量类型">内建变量类型</h4>
<ul>
<li>bool,string</li>
<li>(u)int, (u)int8, (u)int16, (u)int32, (u)int, uintptr</li>
<li>byte, rune</li>
<li>float32, float64, complex64, complex128</li>
<li>变量类型写在变量名之后</li>
<li>编译器可推测变量类型</li>
<li>没有char, 只有rune</li>
<li>原生支持复数类型</li>
</ul>
<figure class="highlight golang"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs golang"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> (<br>	<span class="hljs-string">&quot;fmt&quot;</span><br>	<span class="hljs-string">&quot;math&quot;</span><br>	<span class="hljs-string">&quot;math/cmplx&quot;</span><br>)<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">euler</span><span class="hljs-params">()</span></span>  &#123;<br>	<span class="hljs-comment">// 欧拉公式 e^(i*Pi) + 1 = 0</span><br>	fmt.Println(cmplx.Exp(<span class="hljs-number">1i</span> * math.Pi) + <span class="hljs-number">1</span>)<br>  fmt.Println(cmplx.Pow(math.E, <span class="hljs-number">1i</span> * math.Pi) + <span class="hljs-number">1</span>)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	euler()<br>&#125;<br><br><span class="hljs-comment">// 打印内容</span><br>(<span class="hljs-number">0</span>+<span class="hljs-number">1.2246467991473515e-16i</span>)<br>(<span class="hljs-number">0</span>+<span class="hljs-number">1.2246467991473515e-16i</span>)<br></code></pre></td></tr></table></figure>
<h4 id="强制类型转换">强制类型转换</h4>
<p>go语言需要开发时强制类型转换，不会自动隐式转换</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">triangle</span><span class="hljs-params">()</span></span>  &#123;<br>	a, b := <span class="hljs-number">3</span>, <span class="hljs-number">4</span><br>	<span class="hljs-keyword">var</span> c <span class="hljs-keyword">int</span> <br>	c = math.Sqrt(a*a + b*b)                    <span class="hljs-comment">// 会在编译前idea便提示报错</span><br>  c = <span class="hljs-keyword">int</span>(math.Sqrt(<span class="hljs-keyword">float64</span>(a * a + b * b)))  <span class="hljs-comment">// 正确写法</span><br>	fmt.Println(c)<br>&#125;<br></code></pre></td></tr></table></figure>
<p>常量未声明类型，其类型是不确定的（数值可以作各种类型使用）</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">consts</span><span class="hljs-params">()</span></span>  &#123;<br>	<span class="hljs-comment">// 强制类型转换</span><br>	<span class="hljs-keyword">const</span> a, b = <span class="hljs-number">3</span>, <span class="hljs-number">4</span><br>	<span class="hljs-keyword">var</span> c <span class="hljs-keyword">int</span><br>	c = <span class="hljs-keyword">int</span>(math.Sqrt(a * a + b * b))    <span class="hljs-comment">// a * a + b * b 部分可以不用加上强制类型转换</span><br>	fmt.Println(c)<br>&#125;<br></code></pre></td></tr></table></figure>
<p>可以利用常量申明枚举类型</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">enums</span><span class="hljs-params">()</span></span>  &#123;<br>	<span class="hljs-keyword">const</span> (<br>		golang = <span class="hljs-literal">iota</span><br>		_<br>		java<br>		python<br>		)<br>	fmt.Println(golang, java, python)<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br><span class="hljs-number">0</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span><br></code></pre></td></tr></table></figure>
<p>可以以<code>iota</code>为基础，生成一系列枚举数</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">enums</span><span class="hljs-params">()</span></span>  &#123;<br>	<span class="hljs-keyword">const</span> (<br>		b = <span class="hljs-number">1</span> &lt;&lt; (<span class="hljs-number">10</span> * <span class="hljs-literal">iota</span>)<br>		kb<br>		mb<br>		gb<br>		tb<br>	)<br>	fmt.Println(b, kb, mb, gb, tb)<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br><span class="hljs-number">1</span> <span class="hljs-number">1024</span> <span class="hljs-number">1048576</span> <span class="hljs-number">1073741824</span> <span class="hljs-number">1099511627776</span><br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/variable.go</p>
<h3 id="指针">指针</h3>
<p>指针不能运算</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> a <span class="hljs-keyword">int</span> = <span class="hljs-number">2</span><br>	<span class="hljs-keyword">var</span> pa *<span class="hljs-keyword">int</span> = &amp;a<br>	*pa = <span class="hljs-number">3</span><br>	fmt.Println(a)<br>&#125;<br><br><span class="hljs-comment">// 运行结果</span><br><span class="hljs-number">3</span><br></code></pre></td></tr></table></figure>
<p>参数传递—只有<em>值传递</em>一种方式</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">swapV</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span></span> &#123;<br>	b, a = a, b<br>	fmt.Println(<span class="hljs-string">&quot;in &quot;</span>, a, b, &amp;a, &amp;b)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">swapRN</span><span class="hljs-params">(a, b *<span class="hljs-keyword">int</span>)</span></span> &#123;<br>	<span class="hljs-comment">// 局部变量交换值（地址）</span><br>	b, a = a, b<br>	fmt.Println(<span class="hljs-string">&quot;in &quot;</span>, a, b, *a, *b)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">swapR</span><span class="hljs-params">(a, b *<span class="hljs-keyword">int</span>)</span></span> &#123;<br>	<span class="hljs-comment">// 交换变量值（地址）指向的值</span><br>	*b, *a = *a, *b<br>	fmt.Println(<span class="hljs-string">&quot;in &quot;</span>, a, b, *a, *b)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">pointerSwap</span><span class="hljs-params">()</span></span>  &#123;<br>	a, b := <span class="hljs-number">3</span>, <span class="hljs-number">4</span><br>	swapV(a, b)<br>	fmt.Println(<span class="hljs-string">&quot;out&quot;</span>, a, b, &amp;a, &amp;b)<br><br>	a, b = <span class="hljs-number">3</span>, <span class="hljs-number">4</span><br>	swapRN(&amp;a, &amp;b)<br>	fmt.Println(<span class="hljs-string">&quot;out&quot;</span>, a, b, &amp;a, &amp;b)<br><br>	a, b = <span class="hljs-number">3</span>, <span class="hljs-number">4</span><br>	swapR(&amp;a, &amp;b)<br>	fmt.Println(<span class="hljs-string">&quot;out&quot;</span>, a, b, &amp;a, &amp;b)<br><br>&#125;<br><br><span class="hljs-comment">// 输出</span><br>in  <span class="hljs-number">4</span> <span class="hljs-number">3</span> <span class="hljs-number">0xc00001e0c8</span> <span class="hljs-number">0xc00001e0d0</span><br>out <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">0xc00001e0b8</span> <span class="hljs-number">0xc00001e0c0</span><br>in  <span class="hljs-number">0xc00001e0c0</span> <span class="hljs-number">0xc00001e0b8</span> <span class="hljs-number">4</span> <span class="hljs-number">3</span><br>out <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">0xc00001e0b8</span> <span class="hljs-number">0xc00001e0c0</span><br>in  <span class="hljs-number">0xc00001e0b8</span> <span class="hljs-number">0xc00001e0c0</span> <span class="hljs-number">4</span> <span class="hljs-number">3</span><br>out <span class="hljs-number">4</span> <span class="hljs-number">3</span> <span class="hljs-number">0xc00001e0b8</span> <span class="hljs-number">0xc00001e0c0</span><br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/pointer.go</p>
<h3 id="容器">容器</h3>
<h4 id="数组">数组</h4>
<p>Go 语言的数组有两种不同的创建方式</p>
<ul>
<li>一种是显式的指定数组大小
<ul>
<li>变量的类型在编译进行到<strong>类型检查</strong>阶段就会被提取出来，随后使用 <a target="_blank" rel="noopener" href="https://draveness.me/golang/tree/cmd/compile/internal/types.NewArray"><code>cmd/compile/internal/types.NewArray</code></a>创建包含数组大小的 <a target="_blank" rel="noopener" href="https://draveness.me/golang/tree/cmd/compile/internal/types.Array"><code>cmd/compile/internal/types.Array</code></a> 结构体。</li>
</ul></li>
<li>一种是使用 <code>[...]T</code> 声明数组
<ul>
<li>Go 语言编译器会在的 <a target="_blank" rel="noopener" href="https://draveness.me/golang/tree/cmd/compile/internal/gc.typecheckcomplit"><code>cmd/compile/internal/gc.typecheckcomplit</code></a> 函数中对该数组的大小进行推导</li>
<li><code>[...]T</code> 这种初始化方式也只是 Go 语言为我们提供的一种语法糖，当我们不想计算数组中的元素个数时可以通过这种方法减少一些工作量</li>
</ul></li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">define</span><span class="hljs-params">()</span></span>  &#123;<br>	<span class="hljs-keyword">var</span> arr1 [<span class="hljs-number">5</span>]<span class="hljs-keyword">int</span><br>	arr2 := [<span class="hljs-number">3</span>]<span class="hljs-keyword">int</span>&#123;<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>&#125;<br>	arr3 := [...]<span class="hljs-keyword">int</span>&#123;<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span>&#125;<br><br>	<span class="hljs-keyword">var</span> grid [<span class="hljs-number">4</span>][<span class="hljs-number">5</span>]<span class="hljs-keyword">bool</span><br>	fmt.Println(arr1, arr2, arr3)<br>	fmt.Println(grid)<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br>[<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>] [<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span>] [<span class="hljs-number">2</span> <span class="hljs-number">4</span> <span class="hljs-number">6</span> <span class="hljs-number">8</span> <span class="hljs-number">10</span>]<br>[[<span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span>] [<span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span>] [<span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span>] [<span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span> <span class="hljs-literal">false</span>]]<br><br></code></pre></td></tr></table></figure>
<p>[5]int和[10]int是不同类型</p>
<p>调用func f(arr [10]int)会<em>拷贝</em>数组</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">printArr</span><span class="hljs-params">(arr [5]<span class="hljs-keyword">int</span>)</span></span>  &#123;<br>	arr[<span class="hljs-number">0</span>] = <span class="hljs-number">100</span><br>	<span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> arr &#123;<br>		fmt.Println(i, v)<br>	&#125;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">arrTest</span><span class="hljs-params">()</span></span>  &#123;<br>	<span class="hljs-keyword">var</span> arr1 [<span class="hljs-number">5</span>]<span class="hljs-keyword">int</span><br>	arr2 := [...]<span class="hljs-keyword">int</span>&#123;<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span>&#125;<br>	fmt.Println()<br>	printArr(arr2)<br>	fmt.Println()<br>	<span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> arr1 &#123;<br>		fmt.Println(i, v)<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br><span class="hljs-number">0</span> <span class="hljs-number">100</span><br><span class="hljs-number">1</span> <span class="hljs-number">0</span><br><span class="hljs-number">2</span> <span class="hljs-number">0</span><br><span class="hljs-number">3</span> <span class="hljs-number">0</span><br><span class="hljs-number">4</span> <span class="hljs-number">0</span><br><br><span class="hljs-number">0</span> <span class="hljs-number">100</span><br><span class="hljs-number">1</span> <span class="hljs-number">4</span><br><span class="hljs-number">2</span> <span class="hljs-number">6</span><br><span class="hljs-number">3</span> <span class="hljs-number">8</span><br><span class="hljs-number">4</span> <span class="hljs-number">10</span><br><br><span class="hljs-number">0</span> <span class="hljs-number">0</span><br><span class="hljs-number">1</span> <span class="hljs-number">0</span><br><span class="hljs-number">2</span> <span class="hljs-number">0</span><br><span class="hljs-number">3</span> <span class="hljs-number">0</span><br><span class="hljs-number">4</span> <span class="hljs-number">0</span><br></code></pre></td></tr></table></figure>
<p>若要改变数组的值 需要传入数组的地址，因此go语言一般不使用数组</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">printArrR</span><span class="hljs-params">(arr *[5]<span class="hljs-keyword">int</span>)</span></span>  &#123;<br>	arr[<span class="hljs-number">0</span>] = <span class="hljs-number">100</span><br>	<span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> arr &#123;<br>		fmt.Println(i, v)<br>	&#125;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">arrTest</span><span class="hljs-params">()</span></span>  &#123;<br>	<span class="hljs-keyword">var</span> arr1 [<span class="hljs-number">5</span>]<span class="hljs-keyword">int</span><br>	printArrR(&amp;arr1)<br>	fmt.Println()<br>	fmt.Println(arr1)<br>&#125;<br><span class="hljs-comment">// 输出</span><br><span class="hljs-number">0</span> <span class="hljs-number">100</span><br><span class="hljs-number">1</span> <span class="hljs-number">0</span><br><span class="hljs-number">2</span> <span class="hljs-number">0</span><br><span class="hljs-number">3</span> <span class="hljs-number">0</span><br><span class="hljs-number">4</span> <span class="hljs-number">0</span><br><br>[<span class="hljs-number">100</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>]<br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/collections/array.go</p>
<h4 id="切片">切片</h4>
<ul>
<li><p>slice可以向后扩展，但不能向前扩展</p></li>
<li><p>s[i]不可超越len(s)，向后扩展不可以超越底层数组cap(s)</p></li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">slice</span><span class="hljs-params">()</span></span> &#123;<br>	arr := [...]<span class="hljs-keyword">int</span>&#123;<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>&#125;<br>	s1 := arr[<span class="hljs-number">2</span>: <span class="hljs-number">6</span>]<br>	fmt.Println(s1)<br>	s2 := s1[<span class="hljs-number">3</span>: <span class="hljs-number">5</span>]<br>	fmt.Println(s2)<br>  s3 := s1[<span class="hljs-number">3</span>:<span class="hljs-number">6</span>]<br>	fmt.Println(s3)<br>&#125;<br><span class="hljs-comment">//输出</span><br>[<span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span>]<br>[<span class="hljs-number">6</span> <span class="hljs-number">7</span>]<br><span class="hljs-built_in">panic</span>: runtime error: slice bounds out of <span class="hljs-keyword">range</span> [:<span class="hljs-number">6</span>] with capacity <span class="hljs-number">5</span><br><br>goroutine <span class="hljs-number">1</span> [running]:<br>main.sliceDefine()<br>        ~/Projects/golang/src/offer/note/slices.<span class="hljs-keyword">go</span>:<span class="hljs-number">20</span> +<span class="hljs-number">0x164</span><br>main.main()<br>        ~/Projects/golang/src/offer/note/ab_test_func.<span class="hljs-keyword">go</span>:<span class="hljs-number">28</span> +<span class="hljs-number">0x20</span><br><br></code></pre></td></tr></table></figure>
<p><img src="/images/golang/slice.png" srcset="/img/loading.gif" lazyload></p>
<ul>
<li><p>向slice添加元素，如果超越cap，系统会自动分配更大的底层数组</p></li>
<li><p>由于值传递的原因，必须接收append的返回值<code>s=append(s, val)</code></p></li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sliceAppend</span><span class="hljs-params">()</span></span> &#123;<br>	arr := [...]<span class="hljs-keyword">int</span>&#123;<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>&#125;<br>	s1 := arr[<span class="hljs-number">2</span>: <span class="hljs-number">6</span>]<br>	fmt.Println(s1, <span class="hljs-built_in">cap</span>(s1), <span class="hljs-built_in">len</span>(s1))<br>	s2 := s1[<span class="hljs-number">3</span>: <span class="hljs-number">5</span>]<br>	fmt.Println(s2)<br>	s3 := <span class="hljs-built_in">append</span>(s2, <span class="hljs-number">10</span>)<br>	s4 := <span class="hljs-built_in">append</span>(s3, <span class="hljs-number">11</span>)<br>	s5 := <span class="hljs-built_in">append</span>(s4, <span class="hljs-number">12</span>)<br>	fmt.Println(<span class="hljs-string">&quot;s3, s4, s5=&quot;</span>, s3, s4, s5)<br>	fmt.Println(arr)<br>  <br>  s6 := <span class="hljs-built_in">append</span>(s1, <span class="hljs-number">10</span>)<br>	s7 := <span class="hljs-built_in">append</span>(s6, <span class="hljs-number">11</span>)<br>	s8 := <span class="hljs-built_in">append</span>(s7, <span class="hljs-number">12</span>)<br>	fmt.Println(<span class="hljs-string">&quot;s6, s7, s8=&quot;</span>, s6, s7, s8)<br>	fmt.Println(<span class="hljs-string">&quot;cap(s6), cap(s7), cap(s8) =&quot;</span>, <span class="hljs-built_in">cap</span>(s6), <span class="hljs-built_in">cap</span>(s7), <span class="hljs-built_in">cap</span>(s8))<br>	fmt.Println(arr)<br>&#125;<br><span class="hljs-comment">// 输出</span><br>[<span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span>] <span class="hljs-number">6</span> <span class="hljs-number">4</span><br>[<span class="hljs-number">6</span> <span class="hljs-number">7</span>]<br>s3, s4, s5= [<span class="hljs-number">6</span> <span class="hljs-number">7</span> <span class="hljs-number">10</span>] [<span class="hljs-number">6</span> <span class="hljs-number">7</span> <span class="hljs-number">10</span> <span class="hljs-number">11</span>] [<span class="hljs-number">6</span> <span class="hljs-number">7</span> <span class="hljs-number">10</span> <span class="hljs-number">11</span> <span class="hljs-number">12</span>]<br><span class="hljs-built_in">cap</span>(s3), <span class="hljs-built_in">cap</span>(s4), <span class="hljs-built_in">cap</span>(s5) = <span class="hljs-number">3</span> <span class="hljs-number">6</span> <span class="hljs-number">6</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> <span class="hljs-number">7</span> <span class="hljs-number">10</span>]<br><br>s6, s7, s8= [<span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> <span class="hljs-number">10</span>] [<span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> <span class="hljs-number">10</span> <span class="hljs-number">11</span>] [<span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> <span class="hljs-number">10</span> <span class="hljs-number">11</span> <span class="hljs-number">12</span>]<br><span class="hljs-built_in">cap</span>(s6), <span class="hljs-built_in">cap</span>(s7), <span class="hljs-built_in">cap</span>(s8) = <span class="hljs-number">6</span> <span class="hljs-number">6</span> <span class="hljs-number">12</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> <span class="hljs-number">10</span> <span class="hljs-number">11</span>]<br><br></code></pre></td></tr></table></figure>
<ul>
<li>Zero value for slice is nil</li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sliceDefine</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> s []<span class="hljs-keyword">int</span><br>	<span class="hljs-keyword">for</span> i :=<span class="hljs-number">0</span>; i &lt;<span class="hljs-number">10</span>; i++ &#123;<br>		fmt.Printf(<span class="hljs-string">&quot;%v, cap(s) = %d, len(s) = %d\n&quot;</span>, s, <span class="hljs-built_in">cap</span>(s), <span class="hljs-built_in">len</span>(s))<br>		s = <span class="hljs-built_in">append</span>(s, <span class="hljs-number">2</span>*i + <span class="hljs-number">1</span>)<br>	&#125;<br><br>	s1 := []<span class="hljs-keyword">int</span>&#123;<span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>&#125;<br>	fmt.Printf(<span class="hljs-string">&quot;%v, cap(s1) = %d, len(s1) = %d\n&quot;</span>, s1, <span class="hljs-built_in">cap</span>(s1), <span class="hljs-built_in">len</span>(s1))<br><br>	s2 := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">int</span>, <span class="hljs-number">8</span>)<br>	fmt.Printf(<span class="hljs-string">&quot;%v, cap(s2) = %d, len(s2) = %d\n&quot;</span>, s2, <span class="hljs-built_in">cap</span>(s2), <span class="hljs-built_in">len</span>(s2))<br><br>	s3 := <span class="hljs-built_in">make</span>([]<span class="hljs-keyword">int</span>, <span class="hljs-number">8</span>, <span class="hljs-number">32</span>)<br>	fmt.Printf(<span class="hljs-string">&quot;%v, cap(s3) = %d, len(s3) = %d\n&quot;</span>, s3, <span class="hljs-built_in">cap</span>(s3), <span class="hljs-built_in">len</span>(s3))<br><br>	<span class="hljs-comment">// 拷贝</span><br>	<span class="hljs-built_in">copy</span>(s2, s1)<br>	fmt.Printf(<span class="hljs-string">&quot;%v, cap(s2) = %d, len(s2) = %d\n&quot;</span>, s2, <span class="hljs-built_in">cap</span>(s2), <span class="hljs-built_in">len</span>(s2))<br><br>	<span class="hljs-comment">// 删除 没有内建函数，只能通过截取+append</span><br>	s4 := <span class="hljs-built_in">append</span>(s2[:<span class="hljs-number">2</span>], s2[<span class="hljs-number">3</span>:]...)<br>	fmt.Printf(<span class="hljs-string">&quot;%v, cap(s4) = %d, len(s4) = %d\n&quot;</span>, s4, <span class="hljs-built_in">cap</span>(s4), <span class="hljs-built_in">len</span>(s4))<br>&#125;<br><br><span class="hljs-comment">//输出</span><br>[], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">0</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">0</span><br>[<span class="hljs-number">1</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">1</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">1</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">2</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">2</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">4</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">3</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span> <span class="hljs-number">7</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">4</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">4</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span> <span class="hljs-number">7</span> <span class="hljs-number">9</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">8</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">5</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span> <span class="hljs-number">7</span> <span class="hljs-number">9</span> <span class="hljs-number">11</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">8</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">6</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span> <span class="hljs-number">7</span> <span class="hljs-number">9</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">8</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">7</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span> <span class="hljs-number">7</span> <span class="hljs-number">9</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span> <span class="hljs-number">15</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">8</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">8</span><br>[<span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">5</span> <span class="hljs-number">7</span> <span class="hljs-number">9</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span> <span class="hljs-number">15</span> <span class="hljs-number">17</span>], <span class="hljs-built_in">cap</span>(s) = <span class="hljs-number">16</span>, <span class="hljs-built_in">len</span>(s) = <span class="hljs-number">9</span><br>[<span class="hljs-number">2</span> <span class="hljs-number">3</span> <span class="hljs-number">4</span>], <span class="hljs-built_in">cap</span>(s1) = <span class="hljs-number">3</span>, <span class="hljs-built_in">len</span>(s1) = <span class="hljs-number">3</span><br>[<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>], <span class="hljs-built_in">cap</span>(s2) = <span class="hljs-number">8</span>, <span class="hljs-built_in">len</span>(s2) = <span class="hljs-number">8</span><br>[<span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>], <span class="hljs-built_in">cap</span>(s3) = <span class="hljs-number">32</span>, <span class="hljs-built_in">len</span>(s3) = <span class="hljs-number">8</span><br>[<span class="hljs-number">2</span> <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>], <span class="hljs-built_in">cap</span>(s2) = <span class="hljs-number">8</span>, <span class="hljs-built_in">len</span>(s2) = <span class="hljs-number">8</span><br>[<span class="hljs-number">2</span> <span class="hljs-number">3</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>], <span class="hljs-built_in">cap</span>(s4) = <span class="hljs-number">8</span>, <span class="hljs-built_in">len</span>(s4) = <span class="hljs-number">7</span><br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/collections/slices.go</p>
<h4 id="map">Map</h4>
<ul>
<li><p>创建<code>make(map[type]type)</code></p></li>
<li><p>key不存在时，获取value类型的初始值，需要<code>if value, ok := m[key]; ok &#123;...&#125;</code> 判断是否存在key</p></li>
<li><p>map使用哈希表，必须可以比较相等</p></li>
<li><p>除了slice, map,function的内建类型都可以作为map的key,Struct类型不包含上述字段时，也可作为key</p></li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">mapDefine</span><span class="hljs-params">()</span></span>  &#123;<br>	m := <span class="hljs-keyword">map</span>[<span class="hljs-keyword">int</span>]<span class="hljs-keyword">string</span>&#123;<br>		<span class="hljs-number">1</span>: <span class="hljs-string">&quot;aa&quot;</span>,<br>		<span class="hljs-number">2</span>: <span class="hljs-string">&quot;bb&quot;</span>,<br>	&#125;<br>	<span class="hljs-keyword">if</span> v, ok := m[<span class="hljs-number">3</span>]; ok &#123;<br>		fmt.Println(v)<br>	&#125; <span class="hljs-keyword">else</span> &#123;<br>		<span class="hljs-built_in">panic</span>(<span class="hljs-string">&quot;key not exists&quot;</span>)<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">//输出</span><br><span class="hljs-built_in">panic</span>: key not exists<br><br>goroutine <span class="hljs-number">1</span> [running]:<br>main.mapDefine()<br>        /Users/wangpeng/Projects/golang/src/offer/note/maps.<span class="hljs-keyword">go</span>:<span class="hljs-number">20</span> +<span class="hljs-number">0x1f6</span><br>main.main()<br>        /Users/wangpeng/Projects/golang/src/offer/note/ab_test_func.<span class="hljs-keyword">go</span>:<span class="hljs-number">32</span> +<span class="hljs-number">0x20</span><br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/collections/maps.go</p>
<h4 id="rune">Rune</h4>
<p>字符串在UTF-8编码中，一个中文占三个字节，</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">strByte</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span></span>  &#123;<br>	<span class="hljs-keyword">if</span> s == <span class="hljs-string">&quot;&quot;</span> &#123;<br>		s = <span class="hljs-string">&quot;yes,我喜欢你！&quot;</span><br>	&#125;<br>	<span class="hljs-keyword">for</span> i, ch := <span class="hljs-keyword">range</span> []<span class="hljs-keyword">byte</span>(s) &#123;<br>		fmt.Printf(<span class="hljs-string">&quot;(%d, %X)&quot;</span>, i, ch)<br>	&#125;<br>	fmt.Println()<br>  <span class="hljs-keyword">for</span> i, ch := <span class="hljs-keyword">range</span> s &#123; <span class="hljs-comment">// ch is a rune 其实是将s进行utf-8解码，解码后的字符会转成unicode,然后放入rune中</span><br>		fmt.Printf(<span class="hljs-string">&quot;(%d, %X)&quot;</span>, i, ch)<br>	&#125;<br>	fmt.Println()<br>  bytes := []<span class="hljs-keyword">byte</span>(s)<br>	<span class="hljs-keyword">for</span> <span class="hljs-built_in">len</span>(bytes) &gt;<span class="hljs-number">0</span> &#123;<br>		ch, size := utf8.DecodeRune(bytes)<br>		bytes = bytes[size:]<br>		fmt.Printf(<span class="hljs-string">&quot;%c &quot;</span>, ch)<br>	&#125;<br>	fmt.Println()<br>	<span class="hljs-keyword">for</span> i, ch := <span class="hljs-keyword">range</span> []<span class="hljs-keyword">rune</span>(s) &#123;<br>		fmt.Printf(<span class="hljs-string">&quot;(%d, %X)&quot;</span>, i, ch)<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br>(<span class="hljs-number">0</span>, <span class="hljs-number">79</span>)(<span class="hljs-number">1</span>, <span class="hljs-number">65</span>)(<span class="hljs-number">2</span>, <span class="hljs-number">73</span>)(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>C)(<span class="hljs-number">4</span>, E6)(<span class="hljs-number">5</span>, <span class="hljs-number">88</span>)(<span class="hljs-number">6</span>, <span class="hljs-number">91</span>)(<span class="hljs-number">7</span>, E5)(<span class="hljs-number">8</span>, <span class="hljs-number">96</span>)(<span class="hljs-number">9</span>, <span class="hljs-number">9</span>C)(<span class="hljs-number">10</span>, E6)(<span class="hljs-number">11</span>, AC)(<span class="hljs-number">12</span>, A2)(<span class="hljs-number">13</span>, E4)(<span class="hljs-number">14</span>, BD)(<span class="hljs-number">15</span>, A0)(<span class="hljs-number">16</span>, EF)(<span class="hljs-number">17</span>, BC)(<span class="hljs-number">18</span>, <span class="hljs-number">81</span>)<br>(<span class="hljs-number">0</span>, <span class="hljs-number">79</span>)(<span class="hljs-number">1</span>, <span class="hljs-number">65</span>)(<span class="hljs-number">2</span>, <span class="hljs-number">73</span>)(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>C)(<span class="hljs-number">4</span>, <span class="hljs-number">6211</span>)(<span class="hljs-number">7</span>, <span class="hljs-number">559</span>C)(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>B22)(<span class="hljs-number">13</span>, <span class="hljs-number">4</span>F60)(<span class="hljs-number">16</span>, FF01)<br>y e s , 我 喜 欢 你 ！<br>(<span class="hljs-number">0</span>, <span class="hljs-number">79</span>)(<span class="hljs-number">1</span>, <span class="hljs-number">65</span>)(<span class="hljs-number">2</span>, <span class="hljs-number">73</span>)(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>C)(<span class="hljs-number">4</span>, <span class="hljs-number">6211</span>)(<span class="hljs-number">5</span>, <span class="hljs-number">559</span>C)(<span class="hljs-number">6</span>, <span class="hljs-number">6</span>B22)(<span class="hljs-number">7</span>, <span class="hljs-number">4</span>F60)(<span class="hljs-number">8</span>, FF01)<br><br></code></pre></td></tr></table></figure>
<p>因此在需要使用rune</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Version: 1.0.0</span><br><span class="hljs-comment"> * Description: 获取字符串中不重复字串最大长度</span><br><span class="hljs-comment"> **/</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">maxNoRepeated</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>  <span class="hljs-comment">// 仅支持英文字符</span><br>	<span class="hljs-comment">// 字符下标映射</span><br>  chNotRepeatIndex := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">byte</span>] <span class="hljs-keyword">int</span>)<br>	<span class="hljs-comment">// 最长串起始位置</span><br>  start := <span class="hljs-number">0</span><br>  <span class="hljs-comment">// 最长串长度</span><br>	maxLength := <span class="hljs-number">0</span><br>	 <span class="hljs-keyword">for</span> i, ch := <span class="hljs-keyword">range</span> []<span class="hljs-keyword">byte</span>(s) &#123;<br>	 	<span class="hljs-keyword">if</span> lastI, ok := chNotRepeatIndex[ch]; ok &amp;&amp; lastI &gt;= start &#123;<br>	 		start = lastI + <span class="hljs-number">1</span><br>		&#125;<br>		<span class="hljs-keyword">if</span> i - start + <span class="hljs-number">1</span> &gt; maxLength &#123;<br>			maxLength = i - start + <span class="hljs-number">1</span><br>		&#125;<br>		chNotRepeatIndex[ch] = i<br>	 &#125;<br>	 <span class="hljs-keyword">return</span> maxLength<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">maxNoRepeatedChn</span><span class="hljs-params">(s <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>  <span class="hljs-comment">// 通过rune</span><br>	chNotRepeatIndex := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">map</span>[<span class="hljs-keyword">rune</span>] <span class="hljs-keyword">int</span>)<br>	start := <span class="hljs-number">0</span><br>	maxLength := <span class="hljs-number">0</span><br>	<span class="hljs-keyword">for</span> i, ch := <span class="hljs-keyword">range</span> []<span class="hljs-keyword">rune</span>(s) &#123;<br>		<span class="hljs-keyword">if</span> lastI, ok := chNotRepeatIndex[ch]; ok &amp;&amp; lastI &gt;= start &#123;<br>			start = lastI + <span class="hljs-number">1</span><br>		&#125;<br>		<span class="hljs-keyword">if</span> i - start + <span class="hljs-number">1</span> &gt; maxLength &#123;<br>			maxLength = i - start + <span class="hljs-number">1</span><br>		&#125;<br>		chNotRepeatIndex[ch] = i<br>	&#125;<br>	<span class="hljs-keyword">return</span> maxLength<br>&#125;<br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/collections/strings.go</p>
<h3 id="面向对象">面向对象</h3>
<p>仅<em>支持封装</em>，不支持继承和多态</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><br><span class="hljs-keyword">type</span> Node <span class="hljs-keyword">struct</span> &#123;<br>	Value       <span class="hljs-keyword">int</span><br>	Left, Right *Node<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(node Node)</span> <span class="hljs-title">Print</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Print(node.Value, <span class="hljs-string">&quot; &quot;</span>)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(node *Node)</span> <span class="hljs-title">SetValue</span><span class="hljs-params">(value <span class="hljs-keyword">int</span>)</span></span> &#123;<br>  <span class="hljs-comment">// 接收者使用指针才可以改变结构内容</span><br>	<span class="hljs-keyword">if</span> node == <span class="hljs-literal">nil</span> &#123;<br>		fmt.Println(<span class="hljs-string">&quot;Setting Value to nil node. Ignored.&quot;</span>)<br>		<span class="hljs-keyword">return</span><br>	&#125;<br>	node.Value = value<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(node Node)</span> <span class="hljs-title">SetValueNotUpdate</span><span class="hljs-params">(value <span class="hljs-keyword">int</span>)</span></span> &#123;<br>  <span class="hljs-comment">// 值传递 node内容无法改变</span><br>	<span class="hljs-keyword">if</span> &amp;node == <span class="hljs-literal">nil</span> &#123;<br>		fmt.Println(<span class="hljs-string">&quot;Setting Value to nil node. Ignored.&quot;</span>)<br>		<span class="hljs-keyword">return</span><br>	&#125;<br>	node.Value = value<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">CreateNode</span><span class="hljs-params">(value <span class="hljs-keyword">int</span>)</span> *<span class="hljs-title">Node</span></span> &#123;<br>  <span class="hljs-comment">// 返回局部变量地址，这样变量会在堆中声明，可以传到外部</span><br>	<span class="hljs-keyword">return</span> &amp;Node&#123;Value: value&#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<p>方法有接收者（值/指针接收者），需要改变内容必须使用指针接收者，结构体过大考虑用指针接收者</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>  node := Node&#123;&#125;<br>	node.Print()<br>	node.SetValueNotUpdate(<span class="hljs-number">10</span>)<br>	node.Print()<br>	node.SetValue(<span class="hljs-number">10</span>)<br>	node.Print()<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br><span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">10</span> <br></code></pre></td></tr></table></figure>
<p>nil也可以调用方法</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>  <span class="hljs-keyword">var</span> pNode *Node<br>	pNode.SetValue(<span class="hljs-number">30</span>)<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br>Setting Value to <span class="hljs-literal">nil</span> node. Ignored.<br></code></pre></td></tr></table></figure>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>  <span class="hljs-keyword">var</span> pNode *Node<br>	pNode.SetValueNotUpdate(<span class="hljs-number">20</span>)<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br><span class="hljs-built_in">panic</span>: runtime error: invalid memory address or <span class="hljs-literal">nil</span> pointer dereference<br>[signal SIGSEGV: segmentation violation code=<span class="hljs-number">0x1</span> addr=<span class="hljs-number">0x0</span> pc=<span class="hljs-number">0x109d0af</span>]<br><br>goroutine <span class="hljs-number">1</span> [running]:<br>main.main()<br>        ～/Projects/golang/src/offer/note/ab_test_func.<span class="hljs-keyword">go</span>:<span class="hljs-number">50</span> +<span class="hljs-number">0x1f</span><br><br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/object/tree.go</p>
<h4 id="封装与包">封装与包</h4>
<p>首字母大写:public，首字母小写:private</p>
<p>为结构体定义的方法需要放在一个包下（可以是不同的文件）</p>
<p>扩充系统类型或者自定义类型方式：定义别名和使用组合</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Queue []<span class="hljs-keyword">int</span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(q *Queue)</span><span class="hljs-title">Push</span><span class="hljs-params">(val <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">error</span></span> &#123;<br>	*q = <span class="hljs-built_in">append</span>(*q, val)<br>	<span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(q *Queue)</span><span class="hljs-title">Pop</span><span class="hljs-params">()</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>,<span class="hljs-keyword">bool</span>)</span></span> &#123;<br>	<span class="hljs-keyword">if</span> q.IsEmpty() &#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, <span class="hljs-literal">false</span><br>	&#125;<br>	head := (*q)[<span class="hljs-number">0</span>]<br>	*q = (*q)[<span class="hljs-number">1</span>:]<br>	<span class="hljs-keyword">return</span> head, <span class="hljs-literal">true</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(q *Queue)</span><span class="hljs-title">IsEmpty</span><span class="hljs-params">()</span> <span class="hljs-title">bool</span></span> &#123;<br>	<span class="hljs-keyword">return</span> <span class="hljs-built_in">len</span>(*q) == <span class="hljs-number">0</span><br>&#125;<br></code></pre></td></tr></table></figure>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Node <span class="hljs-keyword">struct</span> &#123;<br>	Value       <span class="hljs-keyword">int</span><br>	Left, Right *Node<br>&#125;<br><br><span class="hljs-keyword">type</span> MyNode <span class="hljs-keyword">struct</span> &#123;<br>	node *Node<br>&#125;<br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/object/queue.go</p>
<h3 id="接口">接口</h3>
<h4 id="鸭子类型">鸭子类型</h4>
<h5 id="duck-typing">Duck Typing</h5>
<p>接口由使用者定义</p>
<p>​ Python的在运行时才能知道被调用的对象是否实现某个方法</p>
<p>​ Java中编译前，调用的对象就必须实现接口所有方法</p>
<p>接口变量自带指针（参数传递也是值传递），因此几乎不需要使用接口指针</p>
<p><img src="/images/golang/interface.png" srcset="/img/loading.gif" lazyload></p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// offer/note/interfaces/mock/duck.go</span><br><span class="hljs-keyword">package</span> mock<br><br><span class="hljs-keyword">type</span> Duck <span class="hljs-keyword">struct</span> &#123;<br>	Name <span class="hljs-keyword">string</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(d *Duck)</span> <span class="hljs-title">GetName</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> &#123;<br>  <span class="hljs-comment">// 实现者没有指明实现了哪个接口</span><br>	<span class="hljs-keyword">if</span> d.Name != <span class="hljs-string">&quot;&quot;</span> &#123;<br>		<span class="hljs-keyword">return</span> d.Name<br>	&#125; <span class="hljs-keyword">else</span> &#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-string">&quot;这是一个鸭子！&quot;</span><br>	&#125;<br>&#125;<br><br><span class="hljs-comment">// offer/note/interfaces/duckI.go</span><br><span class="hljs-keyword">package</span> interfaces<br><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><br><span class="hljs-keyword">type</span> DuckI <span class="hljs-keyword">interface</span> &#123;<br>  <span class="hljs-comment">// 使用接口者 定义方法</span><br>	GetName() <span class="hljs-keyword">string</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">FindDuck</span><span class="hljs-params">(d DuckI)</span></span>  &#123; <span class="hljs-comment">// 接口变量自带指针</span><br>	name := d.GetName()<br>	fmt.Println(name)<br>&#125;<br><br><span class="hljs-comment">// offer/note/main.go</span><br><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> (<br>	<span class="hljs-string">&quot;offer/note/interfaces&quot;</span><br>	<span class="hljs-string">&quot;offer/note/interfaces/mock&quot;</span><br>)<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>  interfaces.FindDuck(&amp;mock.Duck&#123;&#125;)<br>  interfaces.FindDuck(&amp;mock.Duck&#123;Name:<span class="hljs-string">&quot;这是一只假鸭子&quot;</span>&#125;)<br>&#125;<br><br><br><span class="hljs-comment">// 输出</span><br>这是一个鸭子！<br>这是一只假鸭子<br></code></pre></td></tr></table></figure>
<h5 id="多态">多态</h5>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> MemberRights <span class="hljs-keyword">interface</span> &#123;<br> Information () <span class="hljs-keyword">string</span><br>&#125;<br><br><span class="hljs-keyword">type</span> BronzeMember <span class="hljs-keyword">struct</span> &#123;<br> Discount <span class="hljs-keyword">uint8</span><br>&#125;<br><br><span class="hljs-keyword">type</span> SilverMember <span class="hljs-keyword">struct</span> &#123;<br> Discount <span class="hljs-keyword">uint8</span><br>&#125;<br><br><span class="hljs-keyword">type</span> GoldMember <span class="hljs-keyword">struct</span> &#123;<br> Discount <span class="hljs-keyword">uint8</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(b *BronzeMember)</span> <span class="hljs-title">Information</span> <span class="hljs-params">()</span> <span class="hljs-title">string</span></span> &#123;<br> <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">&quot;Discount:%d&quot;</span>, b.Discount)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *SilverMember)</span> <span class="hljs-title">Information</span> <span class="hljs-params">()</span> <span class="hljs-title">string</span></span> &#123;<br> <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">&quot;Discount:%d&quot;</span>, s.Discount)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(g *GoldMember)</span> <span class="hljs-title">Information</span> <span class="hljs-params">()</span> <span class="hljs-title">string</span></span> &#123;<br> <span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">&quot;Discount:%d&quot;</span>, g.Discount)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">Price</span> <span class="hljs-params">(m MemberRights)</span></span> &#123;<br> fmt.Println(m.Information())<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span> <span class="hljs-params">()</span></span> &#123;<br> b := &amp;BronzeMember&#123;Discount: <span class="hljs-number">9</span>&#125;<br> Price(b)<br> s := &amp;SilverMember&#123;<span class="hljs-number">8</span>&#125;<br> Price(s)<br> g := <span class="hljs-built_in">new</span>(GoldMember)<br> g.Discount = <span class="hljs-number">7</span><br> Price(g)<br>&#125;<br></code></pre></td></tr></table></figure>
<h4 id="任何类型">任何类型</h4>
<p><code>interface&#123;&#125;</code></p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Queue []<span class="hljs-keyword">interface</span>&#123;&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(q *Queue)</span><span class="hljs-title">Push</span><span class="hljs-params">(val <span class="hljs-keyword">interface</span>&#123;&#125;)</span> <span class="hljs-title">error</span></span> &#123;<br>	*q = <span class="hljs-built_in">append</span>(*q, val)<br>	<span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(q *Queue)</span><span class="hljs-title">Pop</span><span class="hljs-params">()</span> <span class="hljs-params">(<span class="hljs-keyword">interface</span>&#123;&#125;,<span class="hljs-keyword">bool</span>)</span></span> &#123;<br>	<span class="hljs-keyword">if</span> q.IsEmpty() &#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, <span class="hljs-literal">false</span><br>	&#125;<br>	head := (*q)[<span class="hljs-number">0</span>]<br>	*q = (*q)[<span class="hljs-number">1</span>:]<br>	<span class="hljs-keyword">return</span> head, <span class="hljs-literal">true</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(q *Queue)</span><span class="hljs-title">IsEmpty</span><span class="hljs-params">()</span> <span class="hljs-title">bool</span></span> &#123;<br>	<span class="hljs-keyword">return</span> <span class="hljs-built_in">len</span>(*q) == <span class="hljs-number">0</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>&#123;<br>  q := interfaces.Queue&#123;&#125;<br>	_ = q.Push(<span class="hljs-string">&quot;asd&quot;</span>)<br>	_ = q.Push(<span class="hljs-number">123</span>)<br>	<span class="hljs-keyword">if</span> v, ok := q.Pop(); ok &#123;<br>		fmt.Println(v)<br>	&#125;<br>	<span class="hljs-keyword">if</span> v, ok := q.Pop(); ok &#123;<br>		fmt.Println(v)<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br>asd<br><span class="hljs-number">123</span><br></code></pre></td></tr></table></figure>
<h4 id="组合">组合</h4>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// offer/note/interfaces/animals.go</span><br><span class="hljs-keyword">package</span> animal<br><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><br><span class="hljs-keyword">type</span> AnimalsI <span class="hljs-keyword">interface</span> &#123;<br>	DuckI<br>	BehaviorI<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">DuckBehavior</span><span class="hljs-params">(a AnimalsI)</span></span>  &#123;<br>	name := a.GetName()<br>	dark := a.Shout(<span class="hljs-string">&quot;呱呱乱叫&quot;</span>)<br>	fmt.Println(name, dark)<br>  fmt.Println(a.String())<br>&#125;<br><br><br><span class="hljs-comment">// offer/note/interfaces/behaviorI.go</span><br><span class="hljs-keyword">package</span> animal<br><br><span class="hljs-keyword">type</span> BehaviorI <span class="hljs-keyword">interface</span> &#123;<br>	Shout(dark <span class="hljs-keyword">string</span>) <span class="hljs-keyword">string</span><br>&#125;<br><br><br><span class="hljs-comment">// offer/note/interfaces/duckI.go</span><br><span class="hljs-keyword">package</span> animal<br><br><span class="hljs-keyword">type</span> DuckI <span class="hljs-keyword">interface</span> &#123;<br>	GetName() <span class="hljs-keyword">string</span><br>&#125;<br><br><br><span class="hljs-comment">// offer/note/interfaces/mock/duck.go</span><br><span class="hljs-keyword">package</span> mock<br><br><span class="hljs-keyword">type</span> Duck <span class="hljs-keyword">struct</span> &#123;<br>	name <span class="hljs-keyword">string</span><br>	bark <span class="hljs-keyword">string</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(d *Duck)</span> <span class="hljs-title">GetName</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> &#123;<br>	<span class="hljs-keyword">if</span> d.name != <span class="hljs-string">&quot;&quot;</span> &#123;<br>		<span class="hljs-keyword">return</span> d.name<br>	&#125; <span class="hljs-keyword">else</span> &#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-string">&quot;这是一个鸭子&quot;</span><br>	&#125;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(d *Duck)</span> <span class="hljs-title">Shout</span><span class="hljs-params">(dark <span class="hljs-keyword">string</span>)</span> <span class="hljs-title">string</span></span> &#123;<br>	<span class="hljs-keyword">if</span> d.bark == <span class="hljs-string">&quot;&quot;</span>&#123;<br>		<span class="hljs-keyword">return</span> <span class="hljs-string">&quot;呱呱呱呱的叫&quot;</span><br>	&#125;<span class="hljs-keyword">else</span> &#123;<br>		<span class="hljs-keyword">return</span> dark<br>	&#125;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(d *Duck)</span> <span class="hljs-title">String</span><span class="hljs-params">()</span> <span class="hljs-title">string</span></span> &#123;<br>	<span class="hljs-keyword">return</span> fmt.Sprintf(<span class="hljs-string">&quot;Duck: &#123; name = %s, bark = %s &#125;&quot;</span>, d.name, d.bark)<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br>这是一个鸭子 呱呱呱呱的叫<br>Duck: &#123; name = , bark =  &#125;<br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/tree/master/go/interfaces</p>
<h4 id="常用接口">常用接口</h4>
<ul>
<li><code>Stringer</code>相当于toString()</li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Stringer <span class="hljs-keyword">interface</span> &#123;<br>	String() <span class="hljs-keyword">string</span><br>&#125;<br></code></pre></td></tr></table></figure>
<ul>
<li><code>Reader</code></li>
<li><code>Writer</code></li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-comment">// io/io.go</span><br><br><span class="hljs-comment">// Reader is the interface that wraps the basic Read method.</span><br><span class="hljs-comment">//</span><br><span class="hljs-comment">// Read reads up to len(p) bytes into p. It returns the number of bytes</span><br><span class="hljs-comment">// read (0 &lt;= n &lt;= len(p)) and any error encountered. Even if Read</span><br><span class="hljs-comment">// returns n &lt; len(p), it may use all of p as scratch space during the call.</span><br><span class="hljs-comment">// If some data is available but not len(p) bytes, Read conventionally</span><br><span class="hljs-comment">// returns what is available instead of waiting for more.</span><br><span class="hljs-comment">//</span><br><span class="hljs-comment">// When Read encounters an error or end-of-file condition after</span><br><span class="hljs-comment">// successfully reading n &gt; 0 bytes, it returns the number of</span><br><span class="hljs-comment">// bytes read. It may return the (non-nil) error from the same call</span><br><span class="hljs-comment">// or return the error (and n == 0) from a subsequent call.</span><br><span class="hljs-comment">// An instance of this general case is that a Reader returning</span><br><span class="hljs-comment">// a non-zero number of bytes at the end of the input stream may</span><br><span class="hljs-comment">// return either err == EOF or err == nil. The next Read should</span><br><span class="hljs-comment">// return 0, EOF.</span><br><span class="hljs-comment">//</span><br><span class="hljs-comment">// Callers should always process the n &gt; 0 bytes returned before</span><br><span class="hljs-comment">// considering the error err. Doing so correctly handles I/O errors</span><br><span class="hljs-comment">// that happen after reading some bytes and also both of the</span><br><span class="hljs-comment">// allowed EOF behaviors.</span><br><span class="hljs-comment">//</span><br><span class="hljs-comment">// Implementations of Read are discouraged from returning a</span><br><span class="hljs-comment">// zero byte count with a nil error, except when len(p) == 0.</span><br><span class="hljs-comment">// Callers should treat a return of 0 and nil as indicating that</span><br><span class="hljs-comment">// nothing happened; in particular it does not indicate EOF.</span><br><span class="hljs-comment">//</span><br><span class="hljs-comment">// Implementations must not retain p.</span><br><span class="hljs-keyword">type</span> Reader <span class="hljs-keyword">interface</span> &#123;<br>	Read(p []<span class="hljs-keyword">byte</span>) (n <span class="hljs-keyword">int</span>, err error)<br>&#125;<br><br><span class="hljs-comment">// Writer is the interface that wraps the basic Write method.</span><br><span class="hljs-comment">//</span><br><span class="hljs-comment">// Write writes len(p) bytes from p to the underlying data stream.</span><br><span class="hljs-comment">// It returns the number of bytes written from p (0 &lt;= n &lt;= len(p))</span><br><span class="hljs-comment">// and any error encountered that caused the write to stop early.</span><br><span class="hljs-comment">// Write must return a non-nil error if it returns n &lt; len(p).</span><br><span class="hljs-comment">// Write must not modify the slice data, even temporarily.</span><br><span class="hljs-comment">//</span><br><span class="hljs-comment">// Implementations must not retain p.</span><br><span class="hljs-keyword">type</span> Writer <span class="hljs-keyword">interface</span> &#123;<br>	Write(p []<span class="hljs-keyword">byte</span>) (n <span class="hljs-keyword">int</span>, err error)<br>&#125;<br><br><span class="hljs-comment">// ReadWriter is the interface that groups the basic Read and Write methods.</span><br><span class="hljs-keyword">type</span> ReadWriter <span class="hljs-keyword">interface</span> &#123;<br>	Reader<br>	Writer<br>&#125;<br></code></pre></td></tr></table></figure>
<h3 id="函数">函数</h3>
<ul>
<li>函数可以有多个返回值，并且这些返回值可以起别名（别名多用于简单函数），别名与调用者的申明变量并无关联</li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">eval</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>, op <span class="hljs-keyword">string</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>, error)</span></span> &#123;<br>	<span class="hljs-keyword">switch</span> op &#123;<br>	<span class="hljs-keyword">case</span> <span class="hljs-string">&quot;+&quot;</span>:<br>		<span class="hljs-keyword">return</span>  a + b, <span class="hljs-literal">nil</span><br>	<span class="hljs-keyword">case</span> <span class="hljs-string">&quot;-&quot;</span>:<br>		<span class="hljs-keyword">return</span> a - b, <span class="hljs-literal">nil</span><br>	<span class="hljs-keyword">case</span> <span class="hljs-string">&quot;*&quot;</span>:<br>		<span class="hljs-keyword">return</span> a * b, <span class="hljs-literal">nil</span><br>	<span class="hljs-keyword">case</span> <span class="hljs-string">&quot;/&quot;</span>:<br>		r, _ := div(a, b)<br>		<span class="hljs-keyword">return</span> r, <span class="hljs-literal">nil</span><br>	<span class="hljs-keyword">default</span>:<br>		<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>, fmt.Errorf(<span class="hljs-string">&quot;unsupported operation&quot;</span>)<br>	&#125;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">div</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(q, r <span class="hljs-keyword">int</span>)</span></span> &#123;<br>	<span class="hljs-keyword">return</span> a/b, a%b<br>&#125;<br></code></pre></td></tr></table></figure>
<ul>
<li><em>一等公民</em> :变量、参数、返回值均可以是函数</li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> (<br>	<span class="hljs-string">&quot;fmt&quot;</span><br>	<span class="hljs-string">&quot;math&quot;</span><br>	<span class="hljs-string">&quot;reflect&quot;</span><br>	<span class="hljs-string">&quot;runtime&quot;</span><br>)<br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">apply</span><span class="hljs-params">(op <span class="hljs-keyword">func</span>(<span class="hljs-keyword">int</span>, <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">float64</span>, <span class="hljs-title">a</span>, <span class="hljs-title">b</span> <span class="hljs-title">int</span>) <span class="hljs-title">float64</span></span> &#123;<br>	<span class="hljs-comment">//</span><br>	p := reflect.ValueOf(op).Pointer()<br>	opName := runtime.FuncForPC(p).Name()<br>	fmt.Printf(<span class="hljs-string">&quot;Calling function %s with params (%d, %d)\n&quot;</span>, opName, a, b)<br>	<span class="hljs-keyword">return</span> op(<span class="hljs-keyword">int</span>(a), <span class="hljs-keyword">int</span>(b))<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">pow</span><span class="hljs-params">(a, b <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">float64</span></span> &#123;<br>	<span class="hljs-keyword">return</span> math.Pow(<span class="hljs-keyword">float64</span>(a), <span class="hljs-keyword">float64</span>(b))<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Println(apply(pow, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>))<br><br>	<span class="hljs-comment">// 匿名函数方式</span><br>	fmt.Println(apply(<span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(f, f2 <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">float64</span></span> &#123;<br>		<span class="hljs-keyword">return</span> math.Pow(<span class="hljs-keyword">float64</span>(f), <span class="hljs-keyword">float64</span>(f2))<br>	&#125;, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>))<br>&#125;<br><br><span class="hljs-comment">// 打印结果</span><br>Calling function main.pow with params (<span class="hljs-number">3</span>, <span class="hljs-number">4</span>)<br><span class="hljs-number">81</span><br>Calling function main.main.func1 with params (<span class="hljs-number">3</span>, <span class="hljs-number">4</span>)<br><span class="hljs-number">81</span><br></code></pre></td></tr></table></figure>
<ul>
<li>可变参数列表，类似于Python中的*args</li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">sum</span><span class="hljs-params">(nums ...<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>	<span class="hljs-comment">// 函数可变参数列表</span><br>	sum := <span class="hljs-number">0</span><br>	<span class="hljs-keyword">for</span> i := <span class="hljs-keyword">range</span> nums &#123;<br>		sum += nums[i]<br>	&#125;<br>	<span class="hljs-keyword">return</span> sum<br>&#125;<br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/functions/func.go</p>
<h4 id="闭包">闭包</h4>
<p><img src="/images/golang/func.png" srcset="/img/loading.gif" lazyload></p>
<p>其中，<code>func(i int)</code>中<code>i</code>为局部变量，<code>sum</code>为自由变量</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">adder</span><span class="hljs-params">()</span> <span class="hljs-title">func</span><span class="hljs-params">(<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>	sum := <span class="hljs-number">0</span><br>	<span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(i <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>		sum += i<br>		<span class="hljs-keyword">return</span> sum<br>	&#125;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestAdder</span><span class="hljs-params">()</span></span>  &#123;<br>	a := adder()<br>	<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10</span> ; i++ &#123;<br>		fmt.Printf(<span class="hljs-string">&quot;0 + ... + %d = %d \n&quot;</span>, i, a(i))<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br><span class="hljs-number">0</span> + ... + <span class="hljs-number">0</span> = <span class="hljs-number">0</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">1</span> = <span class="hljs-number">1</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">2</span> = <span class="hljs-number">3</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">3</span> = <span class="hljs-number">6</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">4</span> = <span class="hljs-number">10</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">5</span> = <span class="hljs-number">15</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">6</span> = <span class="hljs-number">21</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">7</span> = <span class="hljs-number">28</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">8</span> = <span class="hljs-number">36</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">9</span> = <span class="hljs-number">45</span> <br><br><br><span class="hljs-comment">// 正统函数式编程</span><br><span class="hljs-keyword">type</span> iAdder <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(<span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>, iAdder)</span></span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">iAdd</span><span class="hljs-params">(base <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">iAdder</span></span> &#123;<br>	<span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(v <span class="hljs-keyword">int</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">int</span>, iAdder)</span></span> &#123;<br>		<span class="hljs-keyword">return</span> base +v, iAdd(base+v)<br>	&#125;<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestAdder</span><span class="hljs-params">()</span></span> &#123;<br>	a2 := iAdd(<span class="hljs-number">0</span>)<br>	<span class="hljs-keyword">var</span> s <span class="hljs-keyword">int</span><br>	<span class="hljs-keyword">for</span> i := <span class="hljs-number">1</span>; i &lt;<span class="hljs-number">10</span>; i++ &#123;<br>		s, a2 = a2(i)<br>		fmt.Printf(<span class="hljs-string">&quot;0 + ... + %d = %d \n&quot;</span>, i, s)<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br><span class="hljs-number">0</span> + ... + <span class="hljs-number">1</span> = <span class="hljs-number">1</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">2</span> = <span class="hljs-number">3</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">3</span> = <span class="hljs-number">6</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">4</span> = <span class="hljs-number">10</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">5</span> = <span class="hljs-number">15</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">6</span> = <span class="hljs-number">21</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">7</span> = <span class="hljs-number">28</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">8</span> = <span class="hljs-number">36</span> <br><span class="hljs-number">0</span> + ... + <span class="hljs-number">9</span> = <span class="hljs-number">45</span> <br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/blob/master/go/functions/closure.go</p>
<h5 id="python中的闭包">Python中的闭包</h5>
<p>Python原生支持闭包</p>
<p><code>__closure__</code>可以查看闭包内容</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs Python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">adder</span>():</span><br>    s = <span class="hljs-number">0</span><br><br>    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span>(<span class="hljs-params">v: <span class="hljs-built_in">int</span></span>):</span><br>        <span class="hljs-keyword">nonlocal</span> s<br>        s += v<br>        <span class="hljs-keyword">return</span> s<br><br>    <span class="hljs-keyword">return</span> f<br><br><br><span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">&quot;__main__&quot;</span>:<br><br>    a = adder()<br>    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">10</span>):<br>        <span class="hljs-built_in">print</span>(i, a(i), a.__closure__)<br>        <br><span class="hljs-comment"># 输出</span><br><span class="hljs-number">0</span> <span class="hljs-number">0</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb6290</span>&gt;,)<br><span class="hljs-number">1</span> <span class="hljs-number">1</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb62b0</span>&gt;,)<br><span class="hljs-number">2</span> <span class="hljs-number">3</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb62f0</span>&gt;,)<br><span class="hljs-number">3</span> <span class="hljs-number">6</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb6350</span>&gt;,)<br><span class="hljs-number">4</span> <span class="hljs-number">10</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb63d0</span>&gt;,)<br><span class="hljs-number">5</span> <span class="hljs-number">15</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb6470</span>&gt;,)<br><span class="hljs-number">6</span> <span class="hljs-number">21</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb6530</span>&gt;,)<br><span class="hljs-number">7</span> <span class="hljs-number">28</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb6610</span>&gt;,)<br><span class="hljs-number">8</span> <span class="hljs-number">36</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb6710</span>&gt;,)<br><span class="hljs-number">9</span> <span class="hljs-number">45</span> (&lt;cell at <span class="hljs-number">0x7f9048e7d3d0</span>: <span class="hljs-built_in">int</span> <span class="hljs-built_in">object</span> at <span class="hljs-number">0x106eb6830</span>&gt;,)<br></code></pre></td></tr></table></figure>
<h5 id="java中的闭包">Java中的闭包</h5>
<p>1.8以后，可以使用Function接口和Lambda表达式可以创建函数对象；</p>
<p>1.8之前，可以使用Lambda表达式或者匿名内部类也可以实现闭包；</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs Java"><span class="hljs-keyword">import</span> javax.xml.ws.Holder;<br><span class="hljs-keyword">import</span> java.util.function.Function;<br><br><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyTest</span> </span>&#123;<br><br>    <span class="hljs-keyword">final</span> Holder&lt;Integer&gt; sum = <span class="hljs-keyword">new</span> Holder&lt;&gt;(<span class="hljs-number">0</span>);<br><br>    <span class="hljs-keyword">public</span>  Function&lt;Integer, Integer&gt;testClosure()&#123;<br>        <span class="hljs-comment">// 闭包  使用Function接口和Lambda表达式可以创建函数对象</span><br>        <span class="hljs-keyword">return</span> (Integer value) -&gt; &#123;<br>            sum.value += value;<br>            <span class="hljs-keyword">return</span> sum.value;<br>        &#125;;<br>    &#125;<br><br>    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>&#123;<br>        MyTest mt = <span class="hljs-keyword">new</span> MyTest();<br>        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>; i &lt; <span class="hljs-number">10</span>; i++) &#123;<br>            System.out.println(i +<span class="hljs-string">&quot;, &quot;</span>+ mt.testClosure().apply(<span class="hljs-keyword">new</span> Integer(i)));<br>        &#125;<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<h4 id="闭包应用">闭包应用</h4>
<h6 id="为函数实现接口">为函数实现接口</h6>
<h6 id="实现函数遍历二叉树">实现函数遍历二叉树</h6>
<h6 id="单例模式限制流量模式">单例模式,限制流量模式</h6>
<h3 id="文档">文档</h3>
<p><code>godoc -http :6060</code>,生成网页文档</p>
<p><img src="/images/golang/doc.jpg" srcset="/img/loading.gif" lazyload></p>
<p><img src="/images/golang/doc1.jpg" srcset="/img/loading.gif" lazyload></p>
<p><code>go doc 方法名（包括包名）</code>,查看方法注释</p>
<p><img src="/images/golang/doc2.jpg" srcset="/img/loading.gif" lazyload></p>
<p><code>xxx_test.go</code>生成示例</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">ExampleQueue_Pop</span><span class="hljs-params">()</span></span> &#123;<br>	q := Queue&#123;&#125;<br>	_ = q.Push(<span class="hljs-string">&quot;asd&quot;</span>)<br>	_ = q.Push(<span class="hljs-number">123</span>)<br>	<span class="hljs-keyword">if</span> v, ok := q.Pop(); ok &#123;<br>		fmt.Println(v)<br>	&#125;<br>	<span class="hljs-keyword">if</span> v, ok := q.Pop(); ok &#123;<br>		fmt.Println(v)<br>	&#125;<br><br>	<span class="hljs-comment">//Output:</span><br>	<span class="hljs-comment">//asd</span><br>	<span class="hljs-comment">//123</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p><img src="/images/golang/doc_output.jpg" srcset="/img/loading.gif" lazyload></p>
<h3 id="测试">测试</h3>
<p><em>表格驱动</em>测试</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">TestMaxNoRepeatedZhn</span><span class="hljs-params">(t *testing.T)</span></span> &#123;<br>	tests := []<span class="hljs-keyword">struct</span>&#123;<br>		s <span class="hljs-keyword">string</span><br>		ans <span class="hljs-keyword">int</span><br>	&#125;&#123;<br>		&#123;<span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-number">1</span>&#125;,<br>		&#123;<span class="hljs-string">&quot;yes, 我爱gogogo&quot;</span>, <span class="hljs-number">9</span>&#125;,<br>		&#123;<span class="hljs-string">&quot;abcadcb&quot;</span>, <span class="hljs-number">4</span>&#125;,<br>		&#123;<span class="hljs-string">&quot;黑化肥挥发发灰会花飞灰化肥挥发发黑会飞花&quot;</span>, <span class="hljs-number">8</span>&#125;,<br>	&#125;<br><br>	<span class="hljs-keyword">for</span> _, tt := <span class="hljs-keyword">range</span> tests &#123;<br>		act := MaxNoRepeatedZhn(tt.s)<br>		<span class="hljs-keyword">if</span> act != tt.ans &#123;<br>			t.Errorf(<span class="hljs-string">&quot;get %d for input %s , but expect %d&quot;</span>, act, tt.s, tt.ans)<br>		&#125;<br>	&#125;<br>&#125;<br><br><span class="hljs-comment">// 输出</span><br>=== RUN   TestMaxNoRepeatedZhn<br>--- PASS: TestMaxNoRepeatedZhn (<span class="hljs-number">0.00</span>s)<br>PASS<br></code></pre></td></tr></table></figure>
<h4 id="覆盖测试">覆盖测试</h4>
<p><code>go tool cover</code></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs shell">Usage of &#x27;go tool cover&#x27;:<br>Given a coverage profile produced by &#x27;go test&#x27;:<br>        go test -coverprofile=c.out<br><br>Open a web browser displaying annotated source code:<br>        go tool cover -html=c.out    # 常用<br><br>Write out an HTML file instead of launching a web browser:<br>        go tool cover -html=c.out -o coverage.html<br><br>Display coverage percentages to stdout for each function:<br>        go tool cover -func=c.out<br><br>Finally, to generate modified source code with coverage annotations<br>(what go test -cover does):<br>        go tool cover -mode=set -var=CoverageVariableName program.go<br><br>Flags:<br>  -V    print version and exit<br>  -func string<br>        output coverage profile information for each function<br>  -html string<br>        generate HTML representation of coverage profile<br>  -mode string<br>        coverage mode: set, count, atomic<br>  -o string<br>        file for output; default: stdout<br>  -var string<br>        name of coverage variable to generate (default &quot;GoCover&quot;)<br><br>  Only one of -html, -func, or -mode may be set.<br></code></pre></td></tr></table></figure>
<h4 id="benchmark"><code>Benchmark</code></h4>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">BenchmarkMaxNoRepeatedZhn</span><span class="hljs-params">(b *testing.B)</span></span> &#123;<br>	s := <span class="hljs-string">&quot;黑化肥挥发发灰会花飞灰化肥挥发发黑会飞花&quot;</span><br>	ans := <span class="hljs-number">8</span><br><br>	<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; b.N; i++ &#123;<br>		act := MaxNoRepeatedZhn(s)<br>		<span class="hljs-keyword">if</span> act != ans &#123;<br>			b.Errorf(<span class="hljs-string">&quot;get %d for input %s , but expect %d&quot;</span>, act, s, ans)<br>		&#125;<br>	&#125;<br>&#125;<br><br><br><span class="hljs-comment">// 输出</span><br>goos: darwin<br>goarch: amd64<br>pkg: offer/note/collections<br>BenchmarkMaxNoRepeatedZhn<br>BenchmarkMaxNoRepeatedZhn<span class="hljs-number">-8</span>   	 <span class="hljs-number">1097594</span>	      <span class="hljs-number">1024</span> ns/op<br>PASS<br></code></pre></td></tr></table></figure>
<p>https://github.com/weitrue/note/collections/strings_test.go</p>
<h4 id="pprof性能测试">pprof性能测试</h4>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs shell">xxx@xxxdeMacBook-Pro  ~/Projects/golang/src/offer/note/collections master ±✚ go test -bench . -cpuprofile cpu.out<br>goos: darwin<br>goarch: amd64<br>pkg: offer/note/collections<br>BenchmarkMaxNoRepeatedZhn-8      1286594               934 ns/op<br>PASS<br>ok      offer/note/collections  2.656s<br>xxx@xxxdeMacBook-Pro  ~/Projects/golang/src/offer/note/collections master ±✚ go tool pprof cpu.out               <br>Type: cpu<br>Time: Mar 2, 2021 at 6:03pm (CST)<br>Duration: 2.34s, Total samples = 2.05s (87.57%)<br>Entering interactive mode (type &quot;help&quot; for commands, &quot;o&quot; for options)<br>(pprof) web<br>failed to execute dot. Is Graphviz installed? Error: exec: &quot;dot&quot;: executable file not found in $PATH<br>(pprof) <br></code></pre></td></tr></table></figure>
<p>☞<code>failed to execute dot. Is Graphviz installed? Error: exec: "dot": executable file not found in $PATH</code>是因为电脑未安装生成.svg文件的工具<code>Graphviz</code></p>
<h5 id="安装graphviz">安装<code>Graphviz</code></h5>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br></pre></td><td class="code"><pre><code class="hljs shell">brew install graphviz<br>xxx@xxxdeMacBook-Pro  ~/Projects/golang/src/github.com  brew install graphviz<br>Error:<br>  homebrew-core is a shallow clone.<br>  homebrew-cask is a shallow clone.<br>To `brew update`, first run:<br>  git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow<br>  git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow<br>These commands may take a few minutes to run due to the large size of the repositories.<br>This restriction has been made on GitHub&#x27;s request because updating shallow<br>clones is an extremely expensive operation due to the tree layout and traffic of<br>Homebrew/homebrew-core and Homebrew/homebrew-cask. We don&#x27;t do this for you<br>automatically to avoid repeatedly performing an expensive unshallow operation in<br>CI systems (which should instead be fixed to not use shallow clones). Sorry for<br>the inconvenience!<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libpng-1.6.37.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/freetype-2.10.4.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/fontconfig-2.13.1.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/jpeg-9d.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libtiff-4.1.0_1.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">########################################                                 58.1%</span></span><br>curl: (56) LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54<br>Error: Failed to download resource &quot;libtiff&quot;<br>Download failed: https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libtiff-4.1.0_1.big_sur.bottle.tar.gz<br>Warning: Bottle installation failed: building from source.<br>==&gt; Downloading https://download.osgeo.org/libtiff/tiff-4.1.0.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/webp-1.1.0.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gd-2.3.0.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libffi-3.3.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pcre-8.44.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/glib-2.66.2_1.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">#########                                                                14.5%</span></span><br>curl: (56) LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54<br>Error: Failed to download resource &quot;glib&quot;<br>Download failed: https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/glib-2.66.2_1.big_sur.bottle.tar.gz<br>Warning: Bottle installation failed: building from source.<br>==&gt; Downloading https://raw.githubusercontent.com/Homebrew/formula-patches/6164294a75541c278f3863b111791376caa3ad26/glib/hardcoded-paths.diff<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://download.gnome.org/sources/glib/2.66/glib-2.66.2.tar.xz<br>==&gt; Downloading from https://mirrors.ustc.edu.cn/gnome/sources/glib/2.66/glib-2.66.2.tar.xz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/jasper-2.0.22.big_sur.bottle.tar.gz<br>==&gt; Downloading from https://d29vzk4ow07wi7.cloudfront.net/ad3715537b3001b9a8924896e5c4e7eb90b21bb37e7171d964de2008edb13910?response-content-disposition=attachment%3Bfilename%3D%22jasper-2.0.22.big_sur.bo<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/netpbm-10.86.17.big_sur.bottle.tar.gz<br>==&gt; Downloading from https://d29vzk4ow07wi7.cloudfront.net/3540b31b88e9d8fc7288de5dac7b96be6f1c6652c604cfd167113bdf07738ca7?response-content-disposition=attachment%3Bfilename%3D%22netpbm-10.86.17.big_sur.<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gts-0.7.6_2.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/lzo-2.10.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pixman-0.40.0.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/cairo-1.16.0_3.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gdk-pixbuf-2.42.0.big_sur.bottle.tar.gz<br>==&gt; Downloading from https://d29vzk4ow07wi7.cloudfront.net/1819bb48f7487d522a69c564dca6fe5dff4da658269f067e47edccddfaab9440?response-content-disposition=attachment%3Bfilename%3D%22gdk-pixbuf-2.42.0.big_su<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/fribidi-1.0.10.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pkg-config-0.29.2_3.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gobject-introspection-1.66.1_1.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/graphite2-1.3.14.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/icu4c-67.1.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/harfbuzz-2.7.2.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pango-1.48.0.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/librsvg-2.50.2.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################                                                     29.6%</span></span><br>curl: (18) transfer closed with 28187304 bytes remaining to read<br>Error: Failed to download resource &quot;librsvg&quot;<br>Download failed: https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/librsvg-2.50.2.big_sur.bottle.tar.gz<br>Warning: Bottle installation failed: building from source.<br>==&gt; Downloading https://download.gnome.org/sources/librsvg/2.50/librsvg-2.50.2.tar.xz<br>==&gt; Downloading from https://mirrors.ustc.edu.cn/gnome/sources/librsvg/2.50/librsvg-2.50.2.tar.xz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libtool-2.4.6_2.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/graphviz-2.44.1.big_sur.bottle.1.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">#####################################                                    52.9%</span></span><br>curl: (18) transfer closed with 6363689 bytes remaining to read<br>Error: Failed to download resource &quot;graphviz&quot;<br>Download failed: https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/graphviz-2.44.1.big_sur.bottle.1.tar.gz<br>Warning: Bottle installation failed: building from source.<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/autoconf-2.69.big_sur.bottle.4.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/automake-1.16.3.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pkg-config-0.29.2_3.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/c393e3a39326eab27929f0f2ce40cb425e78bd8812166e6d835a08a8bf0c5f56--pkg-config-0.29.2_3.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libpng-1.6.37.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/3bd2e2a75fbfc893d9acc20eeafc5274e260ed2ca39483ccbb1450a734bc6775--libpng-1.6.37.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/freetype-2.10.4.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/1399fc577f7998623378e7bb01f8a716a43eff701304059936d592a76d5a4d31--freetype-2.10.4.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/fontconfig-2.13.1.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/3790f4e94c8e7c868307933e3445a1244aadd794adaa6ed5f743533334489f93--fontconfig-2.13.1.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/jpeg-9d.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/7ed5b41c2937740eca747a8077502454971fbbe02cfb5cfbd9b9e7379345d0cd--jpeg-9d.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libtiff-4.1.0_1.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/webp-1.1.0.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/1ae441623b4c63d896b5566300b24c06d772ff9f2676d7c9bd692ff6b8e22edb--webp-1.1.0.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gd-2.3.0.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/d71eed744db212a24cc7f607842253aacf0e1d25cd7891c884ec7ffc969162ac--gd-2.3.0.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libffi-3.3.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/49892306006d42a1f69ae4b36ff44b37c8e7170f6cf73a20e97f10bf9fa10e72--libffi-3.3.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pcre-8.44.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/9998b74590fa558f4c346e9770a62495d4aca8e992d0e883435e3574303ee241--pcre-8.44.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/glib-2.66.2_1.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/jasper-2.0.22.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/86ba13e63264cbcafb0dbec9e35960e2662f9e4bde0306bd52984bf487e6581a--jasper-2.0.22.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/netpbm-10.86.17.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/9f8fa63491038e9bb811b03f09660342641c7f8132169bdb3800631d8d2b189e--netpbm-10.86.17.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gts-0.7.6_2.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/eab94b3870ce0c63232e9a992963c8a32ea53a7efa8a09e639066b40ae0a132b--gts-0.7.6_2.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/lzo-2.10.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/0020e09d8a2c473efa8db2af4b402358f5184578c801c7a7650de6c8bedca06a--lzo-2.10.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pixman-0.40.0.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/ddf94c89d763f2c63c00ce2090ff16d5abd832ca0e1e9beb2245da3cc159ce41--pixman-0.40.0.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/cairo-1.16.0_3.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/8ad096f68fcc70615ff77f14b50eafbed94e4a261c7860dcda41ba25c7d12f52--cairo-1.16.0_3.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gdk-pixbuf-2.42.0.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/fb191d15b537de812241fe664f4149209c4d58ce3fbdd5e98a292fe495420f39--gdk-pixbuf-2.42.0.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/fribidi-1.0.10.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/9013c8a0aeb1d2fee9a999ef14adfb2416fef4e8399d87a65d753d44a586427b--fribidi-1.0.10.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/gobject-introspection-1.66.1_1.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/a7f9a1bcb83a7d322e495d163f15b4b8f4d0c05649eeacfcef2681a23b3eb8dd--gobject-introspection-1.66.1_1.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/graphite2-1.3.14.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/5ce053636ab73845d956142cfd518a21701d3ec972e73367d204b81619b8b845--graphite2-1.3.14.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/icu4c-67.1.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/ddca8d436054c0f9c8c333d2e8dd957ccd3902680baf619e4baed434c9806998--icu4c-67.1.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/harfbuzz-2.7.2.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/1aead0f1ab97b4307a9c487a3191213ff63fd200d5eb9be947a11e8ca78df24a--harfbuzz-2.7.2.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/pango-1.48.0.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/eded163bf136aa7a73e07f22c8b16f3a406bbd849b865246a95ee89ecd60aa4e--pango-1.48.0.big_sur.bottle.tar.gz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/librsvg-2.50.2.big_sur.bottle.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">##################################################                       71.3%</span></span><br>curl: (18) transfer closed with 11492026 bytes remaining to read<br>Error: Failed to download resource &quot;librsvg&quot;<br>Download failed: https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/librsvg-2.50.2.big_sur.bottle.tar.gz<br>Warning: Bottle installation failed: building from source.<br>==&gt; Downloading https://download.gnome.org/sources/librsvg/2.50/librsvg-2.50.2.tar.xz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/0388827e738392e3705cbb8800e43f279723caf5126ba50c7cd4e1ca5e2af872--librsvg-2.50.2.tar.xz<br>==&gt; Downloading https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/bottles/libtool-2.4.6_2.big_sur.bottle.tar.gz<br>Already downloaded: /Users/wangpeng/Library/Caches/Homebrew/downloads/59a8e4e9bff6153b4cb25fda4de99648330e04fefdd7e9c98f92fa4d049a9f30--libtool-2.4.6_2.big_sur.bottle.tar.gz<br>==&gt; Downloading https://www2.graphviz.org/Packages/stable/portable_source/graphviz-2.44.1.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">###################                                                      28.5%</span></span><br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; Installing dependencies for graphviz: autoconf, automake, pkg-config, libpng, freetype, fontconfig, jpeg, libtiff, webp, gd, libffi, pcre, glib, jasper, netpbm, gts, lzo, pixman, cairo, gdk-pixbuf, fribidi, gobject-introspection, graphite2, icu4c, harfbuzz, pango, librsvg and libtool<br>==&gt; Installing graphviz dependency: autoconf<br>==&gt; Pouring autoconf-2.69.big_sur.bottle.4.tar.gz<br>🍺  /usr/local/Cellar/autoconf/2.69: 68 files, 3.0MB<br>==&gt; Installing graphviz dependency: automake<br>==&gt; Pouring automake-1.16.3.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/automake/1.16.3: 131 files, 3.4MB<br>==&gt; Installing graphviz dependency: pkg-config<br>==&gt; Pouring pkg-config-0.29.2_3.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/pkg-config/0.29.2_3: 11 files, 656.6KB<br>==&gt; Installing graphviz dependency: libpng<br>==&gt; Pouring libpng-1.6.37.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/libpng/1.6.37: 27 files, 1.3MB<br>==&gt; Installing graphviz dependency: freetype<br>==&gt; Pouring freetype-2.10.4.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/freetype/2.10.4: 64 files, 2.3MB<br>==&gt; Installing graphviz dependency: fontconfig<br>==&gt; Pouring fontconfig-2.13.1.big_sur.bottle.tar.gz<br>==&gt; Regenerating font cache, this may take a while<br>==&gt; /usr/local/Cellar/fontconfig/2.13.1/bin/fc-cache -frv<br>🍺  /usr/local/Cellar/fontconfig/2.13.1: 531 files, 3.6MB<br>==&gt; Installing graphviz dependency: jpeg<br>==&gt; Pouring jpeg-9d.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/jpeg/9d: 21 files, 953.8KB<br>==&gt; Installing graphviz dependency: libtiff<br>==&gt; Pouring libtiff-4.1.0_1.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/libtiff/4.1.0_1: 247 files, 4.2MB<br>==&gt; Installing graphviz dependency: webp<br>==&gt; Pouring webp-1.1.0.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/webp/1.1.0: 39 files, 2.4MB<br>==&gt; Installing graphviz dependency: gd<br>==&gt; Pouring gd-2.3.0.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/gd/2.3.0: 34 files, 1.4MB<br>==&gt; Installing graphviz dependency: libffi<br>==&gt; Pouring libffi-3.3.big_sur.bottle.tar.gz<br>==&gt; Caveats<br>libffi is keg-only, which means it was not symlinked into /usr/local,<br>because macOS already provides this software and installing another version in<br>parallel can cause all kinds of trouble.<br><br>For compilers to find libffi you may need to set:<br>  export LDFLAGS=&quot;-L/usr/local/opt/libffi/lib&quot;<br>  export CPPFLAGS=&quot;-I/usr/local/opt/libffi/include&quot;<br><br>For pkg-config to find libffi you may need to set:<br>  export PKG_CONFIG_PATH=&quot;/usr/local/opt/libffi/lib/pkgconfig&quot;<br><br>==&gt; Summary<br>🍺  /usr/local/Cellar/libffi/3.3: 17 files, 540.2KB<br>==&gt; Installing graphviz dependency: pcre<br>==&gt; Pouring pcre-8.44.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/pcre/8.44: 204 files, 5.8MB<br>==&gt; Installing graphviz dependency: glib<br>==&gt; Pouring glib-2.66.2_1.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/glib/2.66.2_1: 436 files, 15.5MB<br>==&gt; Installing graphviz dependency: jasper<br>==&gt; Pouring jasper-2.0.22.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/jasper/2.0.22: 42 files, 1.5MB<br>==&gt; Installing graphviz dependency: netpbm<br>==&gt; Pouring netpbm-10.86.17.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/netpbm/10.86.17: 410 files, 17.7MB<br>==&gt; Installing graphviz dependency: gts<br>==&gt; Pouring gts-0.7.6_2.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/gts/0.7.6_2: 27 files, 1.4MB<br>==&gt; Installing graphviz dependency: lzo<br>==&gt; Pouring lzo-2.10.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/lzo/2.10: 31 files, 570.7KB<br>==&gt; Installing graphviz dependency: pixman<br>==&gt; Pouring pixman-0.40.0.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/pixman/0.40.0: 14 files, 1.3MB<br>==&gt; Installing graphviz dependency: cairo<br>==&gt; Pouring cairo-1.16.0_3.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/cairo/1.16.0_3: 119 files, 5.9MB<br>==&gt; Installing graphviz dependency: gdk-pixbuf<br>==&gt; Pouring gdk-pixbuf-2.42.0.big_sur.bottle.tar.gz<br>==&gt; /usr/local/Cellar/gdk-pixbuf/2.42.0/bin/gdk-pixbuf-query-loaders --update-cache<br>🍺  /usr/local/Cellar/gdk-pixbuf/2.42.0: 149 files, 3.8MB<br>==&gt; Installing graphviz dependency: fribidi<br>==&gt; Pouring fribidi-1.0.10.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/fribidi/1.0.10: 67 files, 669.0KB<br>==&gt; Installing graphviz dependency: gobject-introspection<br>==&gt; Pouring gobject-introspection-1.66.1_1.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/gobject-introspection/1.66.1_1: 191 files, 12.7MB<br>==&gt; Installing graphviz dependency: graphite2<br>==&gt; Pouring graphite2-1.3.14.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/graphite2/1.3.14: 18 files, 291.7KB<br>==&gt; Installing graphviz dependency: icu4c<br>==&gt; Pouring icu4c-67.1.big_sur.bottle.tar.gz<br>==&gt; Caveats<br>icu4c is keg-only, which means it was not symlinked into /usr/local,<br>because macOS provides libicucore.dylib (but nothing else).<br><br>If you need to have icu4c first in your PATH run:<br>  echo &#x27;export PATH=&quot;/usr/local/opt/icu4c/bin:$PATH&quot;&#x27; &gt;&gt; ~/.zshrc<br>  echo &#x27;export PATH=&quot;/usr/local/opt/icu4c/sbin:$PATH&quot;&#x27; &gt;&gt; ~/.zshrc<br><br>For compilers to find icu4c you may need to set:<br>  export LDFLAGS=&quot;-L/usr/local/opt/icu4c/lib&quot;<br>  export CPPFLAGS=&quot;-I/usr/local/opt/icu4c/include&quot;<br><br>For pkg-config to find icu4c you may need to set:<br>  export PKG_CONFIG_PATH=&quot;/usr/local/opt/icu4c/lib/pkgconfig&quot;<br><br>==&gt; Summary<br>🍺  /usr/local/Cellar/icu4c/67.1: 258 files, 71.8MB<br>==&gt; Installing graphviz dependency: harfbuzz<br>==&gt; Pouring harfbuzz-2.7.2.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/harfbuzz/2.7.2: 68 files, 6.4MB<br>==&gt; Installing graphviz dependency: pango<br>==&gt; Pouring pango-1.48.0.big_sur.bottle.tar.gz<br>🍺  /usr/local/Cellar/pango/1.48.0: 64 files, 3MB<br>==&gt; Installing graphviz dependency: librsvg<br>==&gt; Pouring librsvg-2.50.2.big_sur.bottle.tar.gz<br>tar: Error opening archive: Failed to open &#x27;/Users/wangpeng/Library/Caches/Homebrew/downloads/3eb605900a29b02eb026199f14474efc43e313ee2b9de389706c795eebdc24f5--librsvg-2.50.2.big_sur.bottle.tar.gz&#x27;<br>Error: Failure while executing; `tar xof /Users/wangpeng/Library/Caches/Homebrew/downloads/3eb605900a29b02eb026199f14474efc43e313ee2b9de389706c795eebdc24f5--librsvg-2.50.2.big_sur.bottle.tar.gz -C /var/folders/zs/<KEY>0000gn/T/d20210302-22554-102pbtw` exited with 1. Here&#x27;s the output:<br>tar: Error opening archive: Failed to open &#x27;/Users/wangpeng/Library/Caches/Homebrew/downloads/3eb605900a29b02eb026199f14474efc43e313ee2b9de389706c795eebdc24f5--librsvg-2.50.2.big_sur.bottle.tar.gz&#x27;<br><br>Warning: Bottle installation failed: building from source.<br>==&gt; Installing dependencies for librsvg: libssh2 and rust<br>==&gt; Installing librsvg dependency: libssh2<br>==&gt; Pouring libssh2-1.9.0_1.big_sur.bottle.tar.gz<br>tar: Error opening archive: Failed to open &#x27;/Users/wangpeng/Library/Caches/Homebrew/downloads/45db0c196aa97bf6c0a9c6e7787ad2cd0d14d563c03d0f4e0d52392a0f3a1c81--libssh2-1.9.0_1.big_sur.bottle.tar.gz&#x27;<br>Error: Failure while executing; `tar xof /Users/wangpeng/Library/Caches/Homebrew/downloads/45db0c196aa97bf6c0a9c6e7787ad2cd0d14d563c03d0f4e0d52392a0f3a1c81--libssh2-1.9.0_1.big_sur.bottle.tar.gz -C /var/folders/<KEY>T/d20210302-22554-qzrgbb` exited with 1. Here&#x27;s the output:<br>tar: Error opening archive: Failed to open &#x27;/Users/wangpeng/Library/Caches/Homebrew/downloads/45db0c196aa97bf6c0a9c6e7787ad2cd0d14d563c03d0f4e0d52392a0f3a1c81--libssh2-1.9.0_1.big_sur.bottle.tar.gz&#x27;<br><br>Warning: Bottle installation failed: building from source.<br>==&gt; Downloading https://libssh2.org/download/libssh2-1.9.0.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; ./configure --prefix=/usr/local/Cellar/libssh2/1.9.0_1 --disable-examples-build --with-openssl --with-libz --with-libssl-prefix=/usr/local/opt/openssl@1.1<br>==&gt; make install<br>🍺  /usr/local/Cellar/libssh2/1.9.0_1: 184 files, 969.9KB, built in 33 seconds<br>==&gt; Installing librsvg dependency: rust<br>==&gt; Pouring rust-1.47.0.big_sur.bottle.tar.gz<br>tar: Error opening archive: Failed to open &#x27;/Users/wangpeng/Library/Caches/Homebrew/downloads/f1482d118ddb120ff152e8f8aa88afa9bebc5674cc42aebca96249cffbdd8bdb--rust-1.47.0.big_sur.bottle.tar.gz&#x27;<br>Error: Failure while executing; `tar xof /Users/wangpeng/Library/Caches/Homebrew/downloads/f1482d118ddb120ff152e8f8aa88afa9bebc5674cc42aebca96249cffbdd8bdb--rust-1.47.0.big_sur.bottle.tar.gz -C /<KEY>d20210302-22554-16tqegl` exited with 1. Here&#x27;s the output:<br>tar: Error opening archive: Failed to open &#x27;/Users/wangpeng/Library/Caches/Homebrew/downloads/f1482d118ddb120ff152e8f8aa88afa9bebc5674cc42aebca96249cffbdd8bdb--rust-1.47.0.big_sur.bottle.tar.gz&#x27;<br><br>Warning: Bottle installation failed: building from source.<br>==&gt; Downloading https://static.rust-lang.org/dist/rustc-1.47.0-src.tar.gz<br><span class="hljs-meta">#</span><span class="bash"><span class="hljs-comment">####################################################################### 100.0%</span></span><br>==&gt; ./configure --prefix=/usr/local/Cellar/rust/1.47.0 --release-channel=stable<br>==&gt; make<br>Last 15 lines from /Users/wangpeng/Library/Logs/Homebrew/rust/02.make:<br>error: failed to get `cc` as a dependency of package `bootstrap v0.0.0 (/private/tmp/rust-20210302-29879-dftrmf/rustc-1.47.0-src/src/bootstrap)`<br><br>Caused by:<br>  failed to fetch `https://github.com/rust-lang/crates.io-index`<br><br>Caused by:<br>  network failure seems to have happened<br>  if a proxy or similar is necessary `net.git-fetch-with-cli` may help here<br>  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli<br><br>Caused by:<br>  http parser error: stream ended at an unexpected time; class=Http (34)<br>failed to run: /private/tmp/rust-20210302-29879-dftrmf/rustc-1.47.0-src/build/x86_64-apple-darwin/stage0/bin/cargo build --manifest-path /private/tmp/rust-20210302-29879-dftrmf/rustc-1.47.0-src/src/bootstrap/Cargo.toml<br>Build completed unsuccessfully in 0:33:17<br>make: *** [all] Error 1<br><br>READ THIS: https://docs.brew.sh/Troubleshooting<br><br>These open issues may also help:<br>rust 1.50.0 https://github.com/Homebrew/homebrew-core/pull/70922<br>Rust-dependent formulae on Apple Silicon - upstream issue tracker https://github.com/Homebrew/homebrew-core/issues/68301<br></code></pre></td></tr></table></figure>
<h3 id="deferrecover在简单web服务应用">defer/recover在简单web服务应用</h3>
<p>代码结构<img src="/images/golang/web.jpg" srcset="/img/loading.gif" lazyload></p>
<p>https://github.com/weitrue/note/tree/master/go/web/</p>
<h3 id="包管理">包管理</h3>
<h4 id="gopm-获取无法下载的包">gopm 获取无法下载的包</h4>
<p><code>go get -v github.com/gpmgo/gopm</code></p>
<p>github地址：https://github.com/gpmgo/gopm</p>
<p>文档路径：https://github.com/gpmgo/docs/tree/master/zh-CN</p>
<p>安装踩坑：</p>
<figure class="highlight zsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs zsh">github.com/codegangsta/cli: github.com/codegangsta/cli@v1.22.5: parsing go.mod:<br>		module declares its path as: github.com/urfave/cli<br>	        but was required as: github.com/codegangsta/cli<br>	        <br></code></pre></td></tr></table></figure>
<p>关闭go mod即可成功安装</p>
<h3 id="工具">工具</h3>
<div class="note note-info">
            <p><a target="_blank" rel="noopener" href="https://google.github.io/osv-scanner/">OSV-扫描仪</a></p><p><a target="_blank" rel="noopener" href="https://github.com/google/osv-scanner">github</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs shell">- Scan a docker image 扫描基于Debian的docker镜像包:<br>    osv-scanner -D docker_image_name<br><br>- Scan a package lockfile 扫描特定锁定文件:<br>    osv-scanner -L path/to/lockfile<br><br>- Scan an SBOM file 只检查SBOM中依赖项中的漏洞:<br>    osv-scanner -S path/to/sbom_file<br><br>- Scan multiple directories recursively 扫描目录:<br>    osv-scanner -r directory1 directory2 ...<br><br>- Skip scanning git repositories:<br>    osv-scanner --skip-git -r|-D target<br><br>- Output result in JSON format:<br>    osv-scanner --json -D|-L|-S|-r target<br></code></pre></td></tr></table></figure>
          </div>
<div class="note note-info">
            <p><a target="_blank" rel="noopener" href="https://silenceper.com/blog/201609/go-wechat-sdk/">WeChat SDK for Go</a></p>
          </div>
<h5 id="爬虫相关">爬虫相关</h5>
<ul>
<li><a target="_blank" rel="noopener" href="https://github.com/henrylee2cn/pholcus">henrylee2cn/pholcus</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/PuerkitoBio/gocrawl">gocrawl</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/gocolly/colly">colly</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/hu17889/go_spider">hu17889/go_spider</a></li>
</ul>
<h5 id="middleware">Middleware</h5>
<div class="note note-success">
            <p><a target="_blank" rel="noopener" href="https://github.com/valyala/bytebufferpool">bytebufferpool</a></p><ul><li>依托sync.Pool进行了二次封装。</li><li>defaultSize设置每次创建buffer的默认大小,超过maxSize的buffer不会被放回去。</li><li>分组统计不同大小buffer的使用次数,例如0-64bytes的buffer被使用的次数。</li><li>引入校准机制,动态计算defaultSize和maxSize。</li></ul>
          </div>
<h5 id="其他">其他</h5>
<ul>
<li><p><a target="_blank" rel="noopener" href="https://github.com/skip2/go-qrcode">二维码生成</a></p></li>
<li><p><a target="_blank" rel="noopener" href="https://github.com/spf13/viper">viper</a></p></li>
<li><p><a target="_blank" rel="noopener" href="https://github.com/spf13/cobra">CLI applications</a></p></li>
</ul>
<h3 id="qa">Q&amp;A</h3>
<div class="note note-warning">
            <p><span class="label label-danger">go http client protocol error: received DATA after END_STREAM</span></p><p>received DATA after END_STREAM只会存在于http2协议中,因此需要设置http client中的ForceAttempHTTP2=false。</p><p><a target="_blank" rel="noopener" href="https://www.google.com.hk/search?q=go+http+client+protocol+error%3A+received+DATA+after+END_STREAM&amp;ei=gwt2YoaqHKyWseMPkdiP6Aw&amp;ved=0ahUKEwjG97rJ28z3AhUsS2wGHRHsA80Q4dUDCA4&amp;uact=5&amp;oq=go+http+client+protocol+error%3A+received+DATA+after+END_STREAM&amp;gs_lcp=Cgdnd3Mtd2l6EANKBAhBGABKBAhGGABQAFjuOGCcPWgAcAF4AYABlgaIAZkjkgENMC43LjQuMS4wLjIuMZgBAKABAcABAQ&amp;sclient=gws-wiz">解决</a></p>
          </div>
<div class="note note-warning">
            <p><span class="label label-danger">context canceled</span></p><p>增加客户端请求超时时间。</p><p><a target="_blank" rel="noopener" href="https://learnku.com/articles/63884">解决</a></p>
          </div>
<h3 id="面试题">面试题</h3>
<h4 id="基础语法">基础语法</h4>
<p>Q1 <code>=</code> 和 <code>:=</code> 的区别？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p><code>:=</code> 声明+赋值</p>
<p><code>=</code> 仅赋值</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">var</span> foo <span class="hljs-keyword">int</span><br>foo = <span class="hljs-number">10</span><br><span class="hljs-comment">// 等价于</span><br>foo := <span class="hljs-number">10</span><br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q2 指针的作用?</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>指针用来保存变量的地址。</p>
<p>例如</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">var</span> x =  <span class="hljs-number">5</span><br><span class="hljs-keyword">var</span> p *<span class="hljs-keyword">int</span> = &amp;x<br>fmt.Printf(<span class="hljs-string">&quot;x = %d&quot;</span>,  *p) <span class="hljs-comment">// x 可以用 *p 访问</span><br></code></pre></td></tr></table></figure>
<ul>
<li><code>*</code> 运算符，也称为解引用运算符，用于访问地址中的值。</li>
<li><code>＆</code>运算符，也称为地址运算符，用于返回变量的地址。</li>
</ul>

    </div>
</div>
<p>Q3 Go 允许多个返回值吗？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>允许</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">swap</span><span class="hljs-params">(x, y <span class="hljs-keyword">string</span>)</span> <span class="hljs-params">(<span class="hljs-keyword">string</span>, <span class="hljs-keyword">string</span>)</span></span> &#123;<br>   <span class="hljs-keyword">return</span> y, x<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>   a, b := swap(<span class="hljs-string">&quot;A&quot;</span>, <span class="hljs-string">&quot;B&quot;</span>)<br>   fmt.Println(a, b) <span class="hljs-comment">// B A</span><br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q4 Go 有异常类型吗？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>Go 没有异常类型，只有错误类型（Error），通常使用返回值来表示异常状态。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go">f, err := os.Open(<span class="hljs-string">&quot;test.txt&quot;</span>)<br><span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> &#123;<br>    log.Fatal(err)<br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q5 什么是协程（Goroutine）</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>Goroutine 是与其他函数或方法同时运行的函数或方法。 Goroutines 可以被认为是轻量级的线程。 与线程相比，创建 Goroutine 的开销很小。 Go应用程序同时运行数千个 Goroutine 是非常常见的做法。</p>

    </div>
</div>
<p>Q6 如何高效地拼接字符串</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>Go 语言中，字符串是只读的，也就意味着每次修改操作都会创建一个新的字符串。如果需要拼接多次，应使用 <code>strings.Builder</code>，最小化内存拷贝次数。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">var</span> str strings.Builder<br><span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++ &#123;<br>    str.WriteString(<span class="hljs-string">&quot;a&quot;</span>)<br>&#125;<br>fmt.Println(str.String())<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q7 什么是 rune 类型</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ASCII 码只需要 7 bit 就可以完整地表示，但只能表示英文字母在内的128个字符，为了表示世界上大部分的文字系统，发明了 Unicode， 它是ASCII的超集，包含世界上书写系统中存在的所有字符，并为每个代码分配一个标准编号（称为Unicode CodePoint），在 Go 语言中称之为 rune，是 int32 类型的别名。</p>
<p>Go 语言中，字符串的底层表示是 byte (8 bit) 序列，而非 rune (32 bit) 序列。例如下面的例子中 <code>语</code> 和 <code>言</code> 使用 UTF-8 编码后各占 3 个 byte，因此 <code>len("Go语言")</code> 等于 8，当然我们也可以将字符串转换为 rune 序列。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go">fmt.Println(<span class="hljs-built_in">len</span>(<span class="hljs-string">&quot;Go语言&quot;</span>)) <span class="hljs-comment">// 8</span><br>fmt.Println(<span class="hljs-built_in">len</span>([]<span class="hljs-keyword">rune</span>(<span class="hljs-string">&quot;Go语言&quot;</span>))) <span class="hljs-comment">// 4</span><br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q8 如何判断 map 中是否包含某个 key ？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">if</span> val, ok := dict[<span class="hljs-string">&quot;foo&quot;</span>]; ok &#123;<br>    <span class="hljs-comment">//do something here</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p><code>dict["foo"]</code> 有 2 个返回值，val 和 ok，如果 ok 等于 <code>true</code>，则说明 dict 包含 key <code>"foo"</code>，val 将被赋予 <code>"foo"</code> 对应的值。</p>

    </div>
</div>
<p>Q9 Go 支持默认参数或可选参数吗？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>Go 语言不支持可选参数（python 支持），也不支持方法重载（java支持）。</p>

    </div>
</div>
<p>Q10 defer 的执行顺序</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <ul>
<li>多个 defer 语句，遵从后进先出(Last In First Out，LIFO)的原则，最后声明的 defer 语句，最先得到执行。</li>
<li>defer 在 return 语句之后执行，但在函数退出之前，defer 可以修改返回值。</li>
</ul>
<p>例如：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">test</span><span class="hljs-params">()</span> <span class="hljs-title">int</span></span> &#123;<br>	i := <span class="hljs-number">0</span><br>	<span class="hljs-keyword">defer</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> &#123;<br>		fmt.Println(<span class="hljs-string">&quot;defer1&quot;</span>)<br>	&#125;()<br>	<span class="hljs-keyword">defer</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> &#123;<br>		i += <span class="hljs-number">1</span><br>		fmt.Println(<span class="hljs-string">&quot;defer2&quot;</span>)<br>	&#125;()<br>	<span class="hljs-keyword">return</span> i<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Println(<span class="hljs-string">&quot;return&quot;</span>, test())<br>&#125;<br><span class="hljs-comment">// defer2</span><br><span class="hljs-comment">// defer1</span><br><span class="hljs-comment">// return 0</span><br></code></pre></td></tr></table></figure>
<p>这个例子中，可以看到 defer 的执行顺序：后进先出。但是返回值并没有被修改，这是由于 Go 的返回机制决定的，执行 return 语句后，Go 会创建一个临时变量保存返回值，因此，defer 语句修改了局部变量 i，并没有修改返回值。那如果是有名的返回值呢？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">test</span><span class="hljs-params">()</span> <span class="hljs-params">(i <span class="hljs-keyword">int</span>)</span></span> &#123;<br>	i = <span class="hljs-number">0</span><br>	<span class="hljs-keyword">defer</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> &#123;<br>		i += <span class="hljs-number">1</span><br>		fmt.Println(<span class="hljs-string">&quot;defer2&quot;</span>)<br>	&#125;()<br>	<span class="hljs-keyword">return</span> i<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Println(<span class="hljs-string">&quot;return&quot;</span>, test())<br>&#125;<br><span class="hljs-comment">// defer2</span><br><span class="hljs-comment">// return 1</span><br></code></pre></td></tr></table></figure>
<p>这个例子中，返回值被修改了。对于有名返回值的函数，执行 return 语句时，并不会再创建临时变量保存，因此，defer 语句修改了 i，即对返回值产生了影响。</p>

    </div>
</div>
<p>Q11 如何交换 2 个变量的值？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go">a, b := <span class="hljs-string">&quot;A&quot;</span>, <span class="hljs-string">&quot;B&quot;</span><br>a, b = b, a<br>fmt.Println(a, b) <span class="hljs-comment">// B A</span><br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q12 Go 语言 tag 的用处？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>tag 可以理解为 struct 字段的注解，可以用来定义字段的一个或多个属性。框架/工具可以通过反射获取到某个字段定义的属性，采取相应的处理方式。tag 丰富了代码的语义，增强了灵活性。</p>
<p>例如：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;encoding/json&quot;</span><br><br><span class="hljs-keyword">type</span> Stu <span class="hljs-keyword">struct</span> &#123;<br>	Name <span class="hljs-keyword">string</span> <span class="hljs-string">`json:&quot;stu_name&quot;`</span><br>	ID   <span class="hljs-keyword">string</span> <span class="hljs-string">`json:&quot;stu_id&quot;`</span><br>	Age  <span class="hljs-keyword">int</span>    <span class="hljs-string">`json:&quot;-&quot;`</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	buf, _ := json.Marshal(Stu&#123;<span class="hljs-string">&quot;Tom&quot;</span>, <span class="hljs-string">&quot;t001&quot;</span>, <span class="hljs-number">18</span>&#125;)<br>	fmt.Printf(<span class="hljs-string">&quot;%s\n&quot;</span>, buf)<br>&#125;<br></code></pre></td></tr></table></figure>
<p>这个例子使用 tag 定义了结构体字段与 json 字段的转换关系，Name -&gt; <code>stu_name</code>, ID -&gt; <code>stu_id</code>，忽略 Age 字段。很方便地实现了 Go 结构体与不同规范的 json 文本之间的转换。</p>

    </div>
</div>
<p>Q13 如何判断 2 个字符串切片（slice) 是相等的？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>go 语言中可以使用反射 <code>reflect.DeepEqual(a, b)</code> 判断 a、b 两个切片是否相等，但是通常不推荐这么做，使用反射非常影响性能。</p>
<p>通常采用的方式如下，遍历比较切片中的每一个元素（注意处理越界的情况）。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">StringSliceEqualBCE</span><span class="hljs-params">(a, b []<span class="hljs-keyword">string</span>)</span> <span class="hljs-title">bool</span></span> &#123;<br>    <span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(a) != <span class="hljs-built_in">len</span>(b) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span><br>    &#125;<br><br>    <span class="hljs-keyword">if</span> (a == <span class="hljs-literal">nil</span>) != (b == <span class="hljs-literal">nil</span>) &#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span><br>    &#125;<br><br>    b = b[:<span class="hljs-built_in">len</span>(a)]<br>    <span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> a &#123;<br>        <span class="hljs-keyword">if</span> v != b[i] &#123;<br>            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span><br>        &#125;<br>    &#125;<br><br>    <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span><br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q14 字符串打印时，<code>%v</code> 和 <code>%+v</code> 的区别</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p><code>%v</code> 和 <code>%+v</code> 都可以用来打印 struct 的值，区别在于 <code>%v</code> 仅打印各个字段的值，<code>%+v</code> 还会打印各个字段的名称。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Stu <span class="hljs-keyword">struct</span> &#123;<br>	Name <span class="hljs-keyword">string</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Printf(<span class="hljs-string">&quot;%v\n&quot;</span>, Stu&#123;<span class="hljs-string">&quot;Tom&quot;</span>&#125;) <span class="hljs-comment">// &#123;Tom&#125;</span><br>	fmt.Printf(<span class="hljs-string">&quot;%+v\n&quot;</span>, Stu&#123;<span class="hljs-string">&quot;Tom&quot;</span>&#125;) <span class="hljs-comment">// &#123;Name:Tom&#125;</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p>但如果结构体定义了 <code>String()</code> 方法，<code>%v</code> 和 <code>%+v</code> 都会调用 <code>String()</code> 覆盖默认值。</p>

    </div>
</div>
<p>Q15 Go 语言中如何表示枚举值(enums)</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>通常使用常量(const) 来表示枚举值。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> StuType <span class="hljs-keyword">int32</span><br><br><span class="hljs-keyword">const</span> (<br>	Type1 StuType = <span class="hljs-literal">iota</span><br>	Type2<br>	Type3<br>	Type4<br>)<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Println(Type1, Type2, Type3, Type4) <span class="hljs-comment">// 0, 1, 2, 3</span><br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q16 空 struct{} 的用途</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>使用空结构体 struct{} 可以节省内存，一般作为占位符使用，表明这里并不需要一个值。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go">fmt.Println(unsafe.Sizeof(<span class="hljs-keyword">struct</span>&#123;&#125;&#123;&#125;)) <span class="hljs-comment">// 0</span><br></code></pre></td></tr></table></figure>
<p>比如使用 map 表示集合时，只关注 key，value 可以使用 struct{} 作为占位符。如果使用其他类型作为占位符，例如 int，bool，不仅浪费了内存，而且容易引起歧义。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Set <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>]<span class="hljs-keyword">struct</span>&#123;&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	set := <span class="hljs-built_in">make</span>(Set)<br><br>	<span class="hljs-keyword">for</span> _, item := <span class="hljs-keyword">range</span> []<span class="hljs-keyword">string</span>&#123;<span class="hljs-string">&quot;A&quot;</span>, <span class="hljs-string">&quot;A&quot;</span>, <span class="hljs-string">&quot;B&quot;</span>, <span class="hljs-string">&quot;C&quot;</span>&#125; &#123;<br>		set[item] = <span class="hljs-keyword">struct</span>&#123;&#125;&#123;&#125;<br>	&#125;<br>	fmt.Println(<span class="hljs-built_in">len</span>(set)) <span class="hljs-comment">// 3</span><br>	<span class="hljs-keyword">if</span> _, ok := set[<span class="hljs-string">&quot;A&quot;</span>]; ok &#123;<br>		fmt.Println(<span class="hljs-string">&quot;A exists&quot;</span>) <span class="hljs-comment">// A exists</span><br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<p>再比如，使用信道(channel)控制并发时，我们只是需要一个信号，但并不需要传递值，这个时候，也可以使用 struct{} 代替。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	ch := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">struct</span>&#123;&#125;, <span class="hljs-number">1</span>)<br>	<span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> &#123;<br>		&lt;-ch<br>		<span class="hljs-comment">// do something</span><br>	&#125;()<br>	ch &lt;- <span class="hljs-keyword">struct</span>&#123;&#125;&#123;&#125;<br>	<span class="hljs-comment">// ...</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p>再比如，声明只包含方法的结构体。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Lamp <span class="hljs-keyword">struct</span>&#123;&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(l Lamp)</span> <span class="hljs-title">On</span><span class="hljs-params">()</span></span> &#123;<br>        <span class="hljs-built_in">println</span>(<span class="hljs-string">&quot;On&quot;</span>)<br><br>&#125;<br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(l Lamp)</span> <span class="hljs-title">Off</span><span class="hljs-params">()</span></span> &#123;<br>        <span class="hljs-built_in">println</span>(<span class="hljs-string">&quot;Off&quot;</span>)<br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<h4 id="实现原理">实现原理</h4>
<p>Q1 init() 函数是什么时候执行的？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p><code>init()</code> 函数是 Go 程序初始化的一部分。Go 程序初始化先于 main 函数，由 runtime 初始化每个导入的包，初始化顺序不是按照从上到下的导入顺序，而是按照解析的依赖关系，没有依赖的包最先初始化。</p>
<p>每个包首先初始化包作用域的常量和变量（常量优先于变量），然后执行包的 <code>init()</code> 函数。同一个包，甚至是同一个源文件可以有多个 <code>init()</code> 函数。<code>init()</code> 函数没有入参和返回值，不能被其他函数调用，同一个包内多个 <code>init()</code> 函数的执行顺序不作保证。</p>
<p>一句话总结： import –&gt; const –&gt; var –&gt; <code>init()</code> –&gt; <code>main()</code></p>
<p>示例：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">init</span><span class="hljs-params">()</span></span>  &#123;<br>	fmt.Println(<span class="hljs-string">&quot;init1:&quot;</span>, a)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">init</span><span class="hljs-params">()</span></span>  &#123;<br>	fmt.Println(<span class="hljs-string">&quot;init2:&quot;</span>, a)<br>&#125;<br><br><span class="hljs-keyword">var</span> a = <span class="hljs-number">10</span><br><span class="hljs-keyword">const</span> b = <span class="hljs-number">100</span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Println(<span class="hljs-string">&quot;main:&quot;</span>, a)<br>&#125;<br><span class="hljs-comment">// 执行结果</span><br><span class="hljs-comment">// init1: 10</span><br><span class="hljs-comment">// init2: 10</span><br><span class="hljs-comment">// main: 10</span><br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q2 Go 语言的局部变量分配在栈上还是堆上？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>由编译器决定。Go 语言编译器会自动决定把一个变量放在栈还是放在堆，编译器会做逃逸分析(escape analysis)，当发现变量的作用域没有超出函数范围，就可以在栈上，反之则必须分配在堆上。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">foo</span><span class="hljs-params">()</span> *<span class="hljs-title">int</span></span> &#123;<br>	v := <span class="hljs-number">11</span><br>	<span class="hljs-keyword">return</span> &amp;v<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	m := foo()<br>	<span class="hljs-built_in">println</span>(*m) <span class="hljs-comment">// 11</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p><code>foo()</code> 函数中，如果 v 分配在栈上，foo 函数返回时，<code>&amp;v</code> 就不存在了，但是这段函数是能够正常运行的。Go 编译器发现 v 的引用脱离了 foo 的作用域，会将其分配在堆上。因此，main 函数中仍能够正常访问该值。</p>

    </div>
</div>
<p>Q3 2 个 interface 可以比较吗？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>Go 语言中，interface 的内部实现包含了 2 个字段，类型 <code>T</code> 和 值 <code>V</code>，interface 可以使用 <code>==</code> 或 <code>!=</code> 比较。2 个 interface 相等有以下 2 种情况</p>
<ol type="1">
<li>两个 interface 均等于 nil（此时 V 和 T 都处于 unset 状态）</li>
<li>类型 T 相同，且对应的值 V 相等。</li>
</ol>
<p>看下面的例子：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Stu <span class="hljs-keyword">struct</span> &#123;<br>	Name <span class="hljs-keyword">string</span><br>&#125;<br><br><span class="hljs-keyword">type</span> StuInt <span class="hljs-keyword">interface</span>&#123;&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> stu1, stu2 StuInt = &amp;Stu&#123;<span class="hljs-string">&quot;Tom&quot;</span>&#125;, &amp;Stu&#123;<span class="hljs-string">&quot;Tom&quot;</span>&#125;<br>	<span class="hljs-keyword">var</span> stu3, stu4 StuInt = Stu&#123;<span class="hljs-string">&quot;Tom&quot;</span>&#125;, Stu&#123;<span class="hljs-string">&quot;Tom&quot;</span>&#125;<br>	fmt.Println(stu1 == stu2) <span class="hljs-comment">// false</span><br>	fmt.Println(stu3 == stu4) <span class="hljs-comment">// true</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p><code>stu1</code> 和 <code>stu2</code> 对应的类型是 <code>*Stu</code>，值是 Stu 结构体的地址，两个地址不同，因此结果为 false。 <code>stu3</code> 和 <code>stu4</code> 对应的类型是 <code>Stu</code>，值是 Stu 结构体，且各字段相等，因此结果为 true。</p>

    </div>
</div>
<p>Q4 两个 nil 可能不相等吗？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>可能。</p>
<p>接口(interface) 是对非接口值(例如指针，struct等)的封装，内部实现包含 2 个字段，类型 <code>T</code> 和 值 <code>V</code>。一个接口等于 nil，当且仅当 T 和 V 处于 unset 状态（T=nil，V is unset）。</p>
<ul>
<li>两个接口值比较时，会先比较 T，再比较 V。</li>
<li>接口值与非接口值比较时，会先将非接口值尝试转换为接口值，再比较。</li>
</ul>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> p *<span class="hljs-keyword">int</span> = <span class="hljs-literal">nil</span><br>	<span class="hljs-keyword">var</span> i <span class="hljs-keyword">interface</span>&#123;&#125; = p<br>	fmt.Println(i == p) <span class="hljs-comment">// true</span><br>	fmt.Println(p == <span class="hljs-literal">nil</span>) <span class="hljs-comment">// true</span><br>	fmt.Println(i == <span class="hljs-literal">nil</span>) <span class="hljs-comment">// false</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p>上面这个例子中，将一个 nil 非接口值 p 赋值给接口 i，此时，i 的内部字段为<code>(T=*int, V=nil)</code>，i 与 p 作比较时，将 p 转换为接口后再比较，因此 <code>i == p</code>，p 与 nil 比较，直接比较值，所以 <code>p == nil</code>。</p>
<p>但是当 i 与 nil 比较时，会将 nil 转换为接口 <code>(T=nil, V=nil)</code>，与i <code>(T=*int, V=nil)</code> 不相等，因此 <code>i != nil</code>。因此 V 为 nil ，但 T 不为 nil 的接口不等于 nil。</p>

    </div>
</div>
<p>Q5 简述 Go 语言GC(垃圾回收)的工作原理</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>最常见的垃圾回收算法有标记清除(Mark-Sweep) 和引用计数(Reference Count)，Go 语言采用的是标记清除算法。并在此基础上使用了三色标记法和写屏障技术，提高了效率。</p>
<p>标记清除收集器是跟踪式垃圾收集器，其执行过程可以分成标记（Mark）和清除（Sweep）两个阶段：</p>
<ul>
<li>标记阶段 — 从根对象出发查找并标记堆中所有存活的对象；</li>
<li>清除阶段 — 遍历堆中的全部对象，回收未被标记的垃圾对象并将回收的内存加入空闲链表。</li>
</ul>
<p>标记清除算法的一大问题是在标记期间，需要暂停程序（Stop the world，STW），标记结束之后，用户程序才可以继续执行。为了能够异步执行，减少 STW 的时间，Go 语言采用了三色标记法。</p>
<p>三色标记算法将程序中的对象分成白色、黑色和灰色三类。</p>
<ul>
<li>白色：不确定对象。</li>
<li>灰色：存活对象，子对象待处理。</li>
<li>黑色：存活对象。</li>
</ul>
<p>标记开始时，所有对象加入白色集合（这一步需 STW ）。首先将根对象标记为灰色，加入灰色集合，垃圾搜集器取出一个灰色对象，将其标记为黑色，并将其指向的对象标记为灰色，加入灰色集合。重复这个过程，直到灰色集合为空为止，标记阶段结束。那么白色对象即可需要清理的对象，而黑色对象均为根可达的对象，不能被清理。</p>
<p>三色标记法因为多了一个白色的状态来存放不确定对象，所以后续的标记阶段可以并发地执行。当然并发执行的代价是可能会造成一些遗漏，因为那些早先被标记为黑色的对象可能目前已经是不可达的了。所以三色标记法是一个 false negative（假阴性）的算法。</p>
<p>三色标记法并发执行仍存在一个问题，即在 GC 过程中，对象指针发生了改变。比如下面的例子：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">A (黑) -&gt; B (灰) -&gt; C (白) -&gt; D (白)<br></code></pre></td></tr></table></figure>
<p>正常情况下，D 对象最终会被标记为黑色，不应被回收。但在标记和用户程序并发执行过程中，用户程序删除了 C 对 D 的引用，而 A 获得了 D 的引用。标记继续进行，D 就没有机会被标记为黑色了（A 已经处理过，这一轮不会再被处理）。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs shell">A (黑) -&gt; B (灰) -&gt; C (白) <br>  ↓<br> D (白)<br></code></pre></td></tr></table></figure>
<p>为了解决这个问题，Go 使用了内存屏障技术，它是在用户程序读取对象、创建新对象以及更新对象指针时执行的一段代码，类似于一个钩子。垃圾收集器使用了写屏障（Write Barrier）技术，当对象新增或更新时，会将其着色为灰色。这样即使与用户程序并发执行，对象的引用发生改变时，垃圾收集器也能正确处理了。</p>
<p>一次完整的 GC 分为四个阶段：</p>
<ul>
<li>1）标记准备(Mark Setup，需 STW)，打开写屏障(Write Barrier)</li>
<li>2）使用三色标记法标记（Marking, 并发）</li>
<li>3）标记结束(Mark Termination，需 STW)，关闭写屏障。</li>
<li>4）清理(Sweeping, 并发)</li>
</ul>

    </div>
</div>
<p>Q6 函数返回局部变量的指针是否安全？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>这在 Go 中是安全的，Go 编译器将会对每个局部变量进行逃逸分析。如果发现局部变量的作用域超出该函数，则不会将内存分配在栈上，而是分配在堆上。</p>

    </div>
</div>
<p>Q7 非接口非接口的任意类型 T() 都能够调用 <code>*T</code> 的方法吗？反过来呢？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <ul>
<li>一个T类型的值可以调用为<code>*T</code>类型声明的方法，但是仅当此T的值是可寻址(addressable) 的情况下。编译器在调用指针属主方法前，会自动取此T值的地址。因为不是任何T值都是可寻址的，所以并非任何T值都能够调用为类型<code>*T</code>声明的方法。</li>
<li>反过来，一个<code>*T</code>类型的值可以调用为类型T声明的方法，这是因为解引用指针总是合法的。事实上，你可以认为对于每一个为类型 T 声明的方法，编译器都会为类型<code>*T</code>自动隐式声明一个同名和同签名的方法。</li>
</ul>
<p>哪些值是不可寻址的呢？</p>
<ul>
<li>字符串中的字节；</li>
<li>map 对象中的元素（slice 对象中的元素是可寻址的，slice的底层是数组）；</li>
<li>常量；</li>
<li>包级别的函数等。</li>
</ul>
<p>举一个例子，定义类型 T，并为类型 <code>*T</code> 声明一个方法 <code>hello()</code>，变量 t1 可以调用该方法，但是常量 t2 调用该方法时，会产生编译错误。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> T <span class="hljs-keyword">string</span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(t *T)</span> <span class="hljs-title">hello</span><span class="hljs-params">()</span></span> &#123;<br>	fmt.Println(<span class="hljs-string">&quot;hello&quot;</span>)<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> t1 T = <span class="hljs-string">&quot;ABC&quot;</span><br>	t1.hello() <span class="hljs-comment">// hello</span><br>	<span class="hljs-keyword">const</span> t2 T = <span class="hljs-string">&quot;ABC&quot;</span><br>	t2.hello() <span class="hljs-comment">// error: cannot call pointer method on t</span><br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<h4 id="并发编程">并发编程</h4>
<p>Q1 无缓冲的 channel 和 有缓冲的 channel 的区别？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>对于无缓冲的 channel，发送方将阻塞该信道，直到接收方从该信道接收到数据为止，而接收方也将阻塞该信道，直到发送方将数据发送到该信道中为止。</p>
<p>对于有缓存的 channel，发送方在没有空插槽（缓冲区使用完）的情况下阻塞，而接收方在信道为空的情况下阻塞。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	st := time.Now()<br>	ch := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">bool</span>)<br>	<span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">()</span></span>  &#123;<br>		time.Sleep(time.Second * <span class="hljs-number">2</span>)<br>		&lt;-ch<br>	&#125;()<br>	ch &lt;- <span class="hljs-literal">true</span>  <span class="hljs-comment">// 无缓冲，发送方阻塞直到接收方接收到数据。</span><br>	fmt.Printf(<span class="hljs-string">&quot;cost %.1f s\n&quot;</span>, time.Now().Sub(st).Seconds())<br>	time.Sleep(time.Second * <span class="hljs-number">5</span>)<br>&#125;<br></code></pre></td></tr></table></figure>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	st := time.Now()<br>	ch := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">bool</span>, <span class="hljs-number">2</span>)<br>	<span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">()</span></span>  &#123;<br>		time.Sleep(time.Second * <span class="hljs-number">2</span>)<br>		&lt;-ch<br>	&#125;()<br>	ch &lt;- <span class="hljs-literal">true</span><br>	ch &lt;- <span class="hljs-literal">true</span> <span class="hljs-comment">// 缓冲区为 2，发送方不阻塞，继续往下执行</span><br>	fmt.Printf(<span class="hljs-string">&quot;cost %.1f s\n&quot;</span>, time.Now().Sub(st).Seconds()) <span class="hljs-comment">// cost 0.0 s</span><br>	ch &lt;- <span class="hljs-literal">true</span> <span class="hljs-comment">// 缓冲区使用完，发送方阻塞，2s 后接收方接收到数据，释放一个插槽，继续往下执行</span><br>	fmt.Printf(<span class="hljs-string">&quot;cost %.1f s\n&quot;</span>, time.Now().Sub(st).Seconds()) <span class="hljs-comment">// cost 2.0 s</span><br>	time.Sleep(time.Second * <span class="hljs-number">5</span>)<br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q2 什么是协程泄露(Goroutine Leak)？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>协程泄露是指协程创建后，长时间得不到释放，并且还在不断地创建新的协程，最终导致内存耗尽，程序崩溃。常见的导致协程泄露的场景有以下几种：</p>
<ul>
<li>缺少接收器，导致发送阻塞</li>
</ul>
<p>这个例子中，每执行一次 query，则启动1000个协程向信道 ch 发送数字 0，但只接收了一次，导致 999 个协程被阻塞，不能退出。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">query</span><span class="hljs-params">()</span> <span class="hljs-title">int</span></span> &#123;<br>	ch := <span class="hljs-built_in">make</span>(<span class="hljs-keyword">chan</span> <span class="hljs-keyword">int</span>)<br>	<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++ &#123;<br>		<span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> &#123; ch &lt;- <span class="hljs-number">0</span> &#125;()<br>	&#125;<br>	<span class="hljs-keyword">return</span> &lt;-ch<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">4</span>; i++ &#123;<br>		query()<br>		fmt.Printf(<span class="hljs-string">&quot;goroutines: %d\n&quot;</span>, runtime.NumGoroutine())<br>	&#125;<br>&#125;<br><span class="hljs-comment">// goroutines: 1001</span><br><span class="hljs-comment">// goroutines: 2000</span><br><span class="hljs-comment">// goroutines: 2999</span><br><span class="hljs-comment">// goroutines: 3998</span><br></code></pre></td></tr></table></figure>
<ul>
<li>缺少发送器，导致接收阻塞</li>
</ul>
<p>那同样的，如果启动 1000 个协程接收信道的信息，但信道并不会发送那么多次的信息，也会导致接收协程被阻塞，不能退出。</p>
<ul>
<li>死锁(dead lock)</li>
</ul>
<p>两个或两个以上的协程在执行过程中，由于竞争资源或者由于彼此通信而造成阻塞，这种情况下，也会导致协程被阻塞，不能退出。</p>
<ul>
<li>无限循环(infinite loops)</li>
</ul>
<p>这个例子中，为了避免网络等问题，采用了无限重试的方式，发送 HTTP 请求，直到获取到数据。那如果 HTTP 服务宕机，永远不可达，导致协程不能退出，发生泄漏。</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">request</span><span class="hljs-params">(url <span class="hljs-keyword">string</span>, wg *sync.WaitGroup)</span></span> &#123;<br>	i := <span class="hljs-number">0</span><br>	<span class="hljs-keyword">for</span> &#123;<br>		<span class="hljs-keyword">if</span> _, err := http.Get(url); err == <span class="hljs-literal">nil</span> &#123;<br>			<span class="hljs-comment">// write to db</span><br>			<span class="hljs-keyword">break</span><br>		&#125;<br>		i++<br>		<span class="hljs-keyword">if</span> i &gt;= <span class="hljs-number">3</span> &#123;<br>			<span class="hljs-keyword">break</span><br>		&#125;<br>		time.Sleep(time.Second)<br>	&#125;<br>	wg.Done()<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> wg sync.WaitGroup<br>	<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++ &#123;<br>		wg.Add(<span class="hljs-number">1</span>)<br>		<span class="hljs-keyword">go</span> request(fmt.Sprintf(<span class="hljs-string">&quot;https://127.0.0.1:8080/%d&quot;</span>, i), &amp;wg)<br>	&#125;<br>	wg.Wait()<br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>Q3 Go 可以限制运行时操作系统线程的数量吗？</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <blockquote>
<p>The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously. There is no limit to the number of threads that can be blocked in system calls on behalf of Go code; those do not count against the GOMAXPROCS limit.</p>
</blockquote>
<p>可以使用环境变量 <code>GOMAXPROCS</code> 或 <code>runtime.GOMAXPROCS(num int)</code> 设置，例如：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">runtime.GOMAXPROCS(1) // 限制同时执行Go代码的操作系统线程数为 1<br></code></pre></td></tr></table></figure>
<p>从官方文档的解释可以看到，<code>GOMAXPROCS</code> 限制的是同时执行用户态 Go 代码的操作系统线程的数量，但是对于被系统调用阻塞的线程数量是没有限制的。<code>GOMAXPROCS</code> 的默认值等于 CPU 的逻辑核数，同一时间，一个核只能绑定一个线程，然后运行被调度的协程。因此对于 CPU 密集型的任务，若该值过大，例如设置为 CPU 逻辑核数的 2 倍，会增加线程切换的开销，降低性能。对于 I/O 密集型应用，适当地调大该值，可以提高 I/O 吞吐率。</p>

    </div>
</div>
<h4 id="代码输出">代码输出</h4>
<h5 id="常量与变量">常量与变量</h5>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">const</span> (<br>		a, b = <span class="hljs-string">&quot;golang&quot;</span>, <span class="hljs-number">100</span><br>		d, e<br>		f <span class="hljs-keyword">bool</span> = <span class="hljs-literal">true</span><br>		g<br>	)<br>	fmt.Println(d, e, g)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>golang 100 true</p>
<p>在同一个 const group 中，如果常量定义与前一行的定义一致，则可以省略类型和值。编译时，会按照前一行的定义自动补全。即等价于</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">const</span> (<br>		a, b = <span class="hljs-string">&quot;golang&quot;</span>, <span class="hljs-number">100</span><br>		d, e = <span class="hljs-string">&quot;golang&quot;</span>, <span class="hljs-number">100</span><br>		f <span class="hljs-keyword">bool</span> = <span class="hljs-literal">true</span><br>		g <span class="hljs-keyword">bool</span> = <span class="hljs-literal">true</span><br>	)<br>	fmt.Println(d, e, g)<br>&#125;<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">const</span> N = <span class="hljs-number">100</span><br>	<span class="hljs-keyword">var</span> x <span class="hljs-keyword">int</span> = N<br><br>	<span class="hljs-keyword">const</span> M <span class="hljs-keyword">int32</span> = <span class="hljs-number">100</span><br>	<span class="hljs-keyword">var</span> y <span class="hljs-keyword">int</span> = M<br>	fmt.Println(x, y)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>编译失败：cannot use M (type int32) as type int in assignment</p>
<p>Go 语言中，常量分为无类型常量和有类型常量两种，<code>const N = 100</code>，属于无类型常量，赋值给其他变量时，如果字面量能够转换为对应类型的变量，则赋值成功，例如，<code>var x int = N</code>。但是对于有类型的常量 <code>const M int32 = 100</code>，赋值给其他变量时，需要类型匹配才能成功，所以显示地类型转换：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">var</span> y <span class="hljs-keyword">int</span> = <span class="hljs-keyword">int</span>(M)<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> a <span class="hljs-keyword">int8</span> = <span class="hljs-number">-1</span><br>	<span class="hljs-keyword">var</span> b <span class="hljs-keyword">int8</span> = <span class="hljs-number">-128</span> / a<br>	fmt.Println(b)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>-128</p>
<p>int8 能表示的数字的范围是 [-2^7, 2^7-1]，即 [-128, 127]。-128 是无类型常量，转换为 int8，再除以变量 -1，结果为 128，常量除以变量，结果是一个变量。变量转换时允许溢出，符号位变为1，转为补码后恰好等于 -128。</p>
<p>对于有符号整型，最高位是是符号位，计算机用补码表示负数。补码 = 原码取反加一。</p>
<p>例如：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs shell">-1 :  11111111<br>00000001(原码)    11111110(取反)    11111111(加一)<br>-128：    <br>10000000(原码)    01111111(取反)    10000000(加一)<br><br>-1 + 1 = 0<br>11111111 + 00000001 = 00000000(最高位溢出省略)<br>-128 + 127 = -1<br>10000000 + 01111111 = 11111111<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">const</span> a <span class="hljs-keyword">int8</span> = <span class="hljs-number">-1</span><br>	<span class="hljs-keyword">var</span> b <span class="hljs-keyword">int8</span> = <span class="hljs-number">-128</span> / a<br>	fmt.Println(b)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>编译失败：constant 128 overflows int8</p>
<p>-128 和 a 都是常量，在编译时求值，-128 / a = 128，两个常量相除，结果也是一个常量，常量类型转换时不允许溢出，因而编译失败。</p>

    </div>
</div>
<p>下面的程序的运行结果是？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>       i := <span class="hljs-number">1</span><br>       j := <span class="hljs-number">2</span><br>       i, j = j, i<br>       fmt.Printf(<span class="hljs-string">&quot;%d%d\n&quot;</span>, i, j)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>21</p>

    </div>
</div>
<p>下面的程序的运行结果是？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> <span class="hljs-string">&quot;fmt&quot;</span><br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>    <span class="hljs-keyword">var</span> i <span class="hljs-keyword">float64</span> = <span class="hljs-number">3</span> / <span class="hljs-number">2</span><br>    fmt.Print(i)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs shell">1<br>关键在于 3/2 计算的结果，3、2 这是整型字面值常量。根据 Go 的规则，3/2 结果也是整型，因此是 1，最后会隐式转换为 float64。<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下面的程序的运行结果是？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">incr</span><span class="hljs-params">(p *<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>        *p++<br>        <span class="hljs-keyword">return</span> *p<br>&#125;<br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>        v := <span class="hljs-number">1</span><br>        incr(&amp;v)<br>        fmt.Println(v)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">2<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下面的程序的运行结果是？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">incr</span><span class="hljs-params">(v <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>        v++<br>        <span class="hljs-keyword">return</span> v<br>&#125;<br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>        v := <span class="hljs-number">1</span><br>        incr(v)<br>        fmt.Println(v)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">1<br></code></pre></td></tr></table></figure>

    </div>
</div>
<h5 id="作用域">作用域</h5>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> err error<br>	<span class="hljs-keyword">if</span> err == <span class="hljs-literal">nil</span> &#123;<br>		err := fmt.Errorf(<span class="hljs-string">&quot;err&quot;</span>)<br>		fmt.Println(<span class="hljs-number">1</span>, err)<br>	&#125;<br>	<span class="hljs-keyword">if</span> err != <span class="hljs-literal">nil</span> &#123;<br>		fmt.Println(<span class="hljs-number">2</span>, err)<br>	&#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>1 err</p>
<p><code>:=</code> 表示声明并赋值，<code>=</code> 表示仅赋值。</p>
<p>变量的作用域是大括号，因此在第一个 if 语句 <code>if err == nil</code> 内部重新声明且赋值了与外部变量同名的局部变量 err。对该局部变量的赋值不会影响到外部的 err。因此第二个 if 语句 <code>if err != nil</code> 不成立。所以只打印了 <code>1 err</code>。</p>

    </div>
</div>
<p>下面的程序的运行结果是?</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>        x := <span class="hljs-number">1</span><br>        &#123;<br>            x := <span class="hljs-number">2</span><br>            fmt.Print(x)<br>        &#125;<br>        fmt.Println(x)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>21</p>

    </div>
</div>
<h5 id="defer-延迟调用">defer 延迟调用</h5>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> T <span class="hljs-keyword">struct</span>&#123;&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(t T)</span> <span class="hljs-title">f</span><span class="hljs-params">(n <span class="hljs-keyword">int</span>)</span> <span class="hljs-title">T</span></span> &#123;<br>	fmt.Print(n)<br>	<span class="hljs-keyword">return</span> t<br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	<span class="hljs-keyword">var</span> t T<br>	<span class="hljs-keyword">defer</span> t.f(<span class="hljs-number">1</span>).f(<span class="hljs-number">2</span>)<br>	fmt.Print(<span class="hljs-number">3</span>)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>132</p>
<p>defer 延迟调用时，需要保存函数指针和参数，因此链式调用的情况下，除了最后一个函数/方法外的函数/方法都会在调用时直接执行。也就是说 <code>t.f(1)</code> 直接执行，然后执行 <code>fmt.Print(3)</code>，最后函数返回时再执行 <code>.f(2)</code>，因此输出是 132。</p>

    </div>
</div>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">f</span><span class="hljs-params">(n <span class="hljs-keyword">int</span>)</span></span> &#123;<br>	<span class="hljs-keyword">defer</span> fmt.Println(n)<br>	n += <span class="hljs-number">100</span><br>&#125;<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	f(<span class="hljs-number">1</span>)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>1</p>
<p>打印 1 而不是 101。defer 语句执行时，会将需要延迟调用的函数和参数保存起来，也就是说，执行到 defer 时，参数 n(此时等于1) 已经被保存了。因此后面对 n 的改动并不会影响延迟函数调用的结果。</p>

    </div>
</div>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	n := <span class="hljs-number">1</span><br>	<span class="hljs-keyword">defer</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> &#123;<br>		fmt.Println(n)<br>	&#125;()<br>	n += <span class="hljs-number">100</span><br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>101</p>
<p>匿名函数没有通过传参的方式将 n 传入，因此匿名函数内的 n 和函数外部的 n 是同一个，延迟执行时，已经被改变为 101。</p>

    </div>
</div>
<p>下列代码的输出是：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>	n := <span class="hljs-number">1</span><br>	<span class="hljs-keyword">if</span> n == <span class="hljs-number">1</span> &#123;<br>		<span class="hljs-keyword">defer</span> fmt.Println(n)<br>		n += <span class="hljs-number">100</span><br>	&#125;<br>	fmt.Println(n)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-number">101</span><br><span class="hljs-number">1</span><br></code></pre></td></tr></table></figure>
<p>先打印 101，再打印 1。defer 的作用域是函数，而不是代码块，因此 if 语句退出时，defer 不会执行，而是等 101 打印后，整个函数返回时，才会执行。</p>

    </div>
</div>
<p>下面的程序的运行结果是?</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">5</span>; i++ &#123;<br>        <span class="hljs-keyword">defer</span> fmt.Printf(<span class="hljs-string">&quot;%d &quot;</span>, i)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-number">4</span> <span class="hljs-number">3</span> <span class="hljs-number">2</span> <span class="hljs-number">1</span> <span class="hljs-number">0</span><br></code></pre></td></tr></table></figure>

    </div>
</div>
<h5 id="数组与切片">数组与切片</h5>
<p>下面的程序的运行结果是?</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>        x := []<span class="hljs-keyword">string</span>&#123;<span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-string">&quot;b&quot;</span>, <span class="hljs-string">&quot;c&quot;</span>&#125;<br>        <span class="hljs-keyword">for</span> v := <span class="hljs-keyword">range</span> x &#123;<br>            fmt.Print(v)<br>        &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-number">012</span><br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下面的程序的运行结果是？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>        x := []<span class="hljs-keyword">string</span>&#123;<span class="hljs-string">&quot;a&quot;</span>, <span class="hljs-string">&quot;b&quot;</span>, <span class="hljs-string">&quot;c&quot;</span>&#125;<br>        <span class="hljs-keyword">for</span> _, v := <span class="hljs-keyword">range</span> x &#123;<br>            fmt.Print(v)<br>        &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go">abc<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下面的程序的运行结果是?</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>    strs := []<span class="hljs-keyword">string</span>&#123;<span class="hljs-string">&quot;one&quot;</span>, <span class="hljs-string">&quot;two&quot;</span>, <span class="hljs-string">&quot;three&quot;</span>&#125;<br>		<span class="hljs-keyword">for</span> _, s := <span class="hljs-keyword">range</span> strs &#123;<br>        <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">()</span></span> &#123;<br>            time.Sleep(<span class="hljs-number">1</span> * time.Second)<br>            fmt.Printf(<span class="hljs-string">&quot;%s &quot;</span>, s)<br>        &#125;()<br>    &#125;<br>    time.Sleep(<span class="hljs-number">3</span> * time.Second)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go">three three three<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下面的程序的运行结果是?</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>    strs := []<span class="hljs-keyword">string</span>&#123;<span class="hljs-string">&quot;one&quot;</span>, <span class="hljs-string">&quot;two&quot;</span>, <span class="hljs-string">&quot;three&quot;</span>&#125;<br>		<span class="hljs-keyword">for</span> _, s := <span class="hljs-keyword">range</span> strs &#123;<br>        <span class="hljs-keyword">go</span> <span class="hljs-function"><span class="hljs-keyword">func</span><span class="hljs-params">(ss <span class="hljs-keyword">string</span>)</span></span> &#123;<br>			      time.Sleep(<span class="hljs-number">1</span> * time.Second)<br>			      fmt.Printf(<span class="hljs-string">&quot;%s &quot;</span>, ss)<br>		    &#125;(s)<br>    &#125;<br>    time.Sleep(<span class="hljs-number">3</span> * time.Second)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go">three one two / one two three /...<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下面的程序的运行结果是？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">package</span> main<br><br><span class="hljs-keyword">import</span> (<br>    <span class="hljs-string">&quot;fmt&quot;</span><br>)<br><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>    v := [...]<span class="hljs-keyword">int</span>&#123;<span class="hljs-number">1</span>: <span class="hljs-number">2</span>, <span class="hljs-number">3</span>: <span class="hljs-number">4</span>&#125;<br>    fmt.Println(<span class="hljs-built_in">len</span>(v))<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-number">4</span><br>除了 <span class="hljs-keyword">map</span>，array(slice) 初始化时也是可以指定索引的。该题有一个索引 <span class="hljs-number">3</span>，根据数组的特点，必然有小于 <span class="hljs-number">3</span> 的所有也存在，上题中，v 的值是：[<span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">4</span>]<br></code></pre></td></tr></table></figure>

    </div>
</div>
<p>下面的程序的运行结果是？</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Slice []<span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">NewSlice</span><span class="hljs-params">()</span> <span class="hljs-title">Slice</span></span> &#123;<br>         <span class="hljs-keyword">return</span> <span class="hljs-built_in">make</span>(Slice, <span class="hljs-number">0</span>)<br>&#125;<br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s* Slice)</span> <span class="hljs-title">Add</span><span class="hljs-params">(elem <span class="hljs-keyword">int</span>)</span> *<span class="hljs-title">Slice</span></span> &#123;<br>         *s = <span class="hljs-built_in">append</span>(*s, elem)<br>         fmt.Print(elem)<br>         <span class="hljs-keyword">return</span> s<br>&#125;<br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>         s := NewSlice()<br>         <span class="hljs-keyword">defer</span> s.Add(<span class="hljs-number">1</span>).Add(<span class="hljs-number">2</span>)<br>         s.Add(<span class="hljs-number">3</span>)<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-number">132</span><br></code></pre></td></tr></table></figure>

    </div>
</div>
<h4 id="选择题">选择题</h4>
<p>1.下面属于关键字的是（）</p>
<p>A. func</p>
<p>B. def</p>
<p>C. struct</p>
<p>D. class​</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AC</p>

    </div>
</div>
<p>2.定义一个包内全局字符串变量，下面语法正确的是 （）</p>
<p>A. var str string</p>
<p>B. str := “”</p>
<p>C. str = “”</p>
<p>D. var str = “”</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AD</p>

    </div>
</div>
<p>3.通过指针变量 p 访问其成员变量 name，下面语法正确的是（）</p>
<p>A. p.name</p>
<p>B. (*p).name</p>
<p>C. (&amp;p).name</p>
<p>D. p-&gt;name</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AB</p>

    </div>
</div>
<p>4.关于接口和类的说法，下面说法正确的是（）</p>
<p>A. 一个类只需要实现了接口要求的所有函数，我们就说这个类实现了该接口</p>
<p>B. 实现类的时候，只需要关心自己应该提供哪些方法，不用再纠结接口需要拆得多细才合理</p>
<p>C. 类实现接口时，需要导入接口所在的包</p>
<p>D. 接口由使用方按自身需求来定义，使用方无需关心是否有其他模块定义过类似的接口</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABD</p>

    </div>
</div>
<p>5.关于字符串连接，下面语法正确的是（）</p>
<p>A. str := ‘abc’ + ‘123’</p>
<p>B. str := “abc” + “123”</p>
<p>C. str ：= ‘123’ + “abc”</p>
<p>D. fmt.Sprintf(“abc%d”, 123)</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BD</p>

    </div>
</div>
<p>6.关于协程，下面说法正确是（）</p>
<p>A. 协程和线程都可以实现程序的并发执行</p>
<p>B. 线程比协程更轻量级</p>
<p>C. 协程不存在死锁问题</p>
<p>D. 通过channel来进行协程间的通信</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AD</p>

    </div>
</div>
<p>7.关于init函数，下面说法正确的是（）</p>
<p>A. 一个包中，可以包含多个init函数</p>
<p>B. 程序编译时，先执行导入包的init函数，再执行本包内的init函数</p>
<p>C. main包中，不能有init函数</p>
<p>D. init函数可以被其他函数调用</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AB</p>

    </div>
</div>
<p>8.关于循环语句，下面说法正确的有（）</p>
<p>A. 循环语句既支持for关键字，也支持while和do-while</p>
<p>B. 关键字for的基本使用方法与C/C++中没有任何差异</p>
<p>C. for循环支持continue和break来控制循环，但是它提供了一个更高级的break，可以选择中断哪一个循环</p>
<p>D. for循环不支持以逗号为间隔的多个赋值语句，必须使用平行赋值的方式来初始化多个变量</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>CD</p>

    </div>
</div>
<p>9.对于函数定义：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">add</span><span class="hljs-params">(args ...<span class="hljs-keyword">int</span>)</span> <span class="hljs-title">int</span></span> &#123;<br>        sum := <span class="hljs-number">0</span><br>        <span class="hljs-keyword">for</span> _, arg := <span class="hljs-keyword">range</span> args &#123;<br>            sum += arg<br>        &#125;<br>        <span class="hljs-keyword">return</span> sum<br>&#125;<br></code></pre></td></tr></table></figure>
<p>下面对add函数调用正确的是（）</p>
<p>A. add(1, 2)</p>
<p>B. add(1, 3, 7)</p>
<p>C. add([]int{1, 2})</p>
<p>D. add([]int{1, 3, 7}...)</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABD</p>

    </div>
</div>
<p>10.关于类型转化，下面语法正确的是（）</p>
<ol type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> MyInt <span class="hljs-keyword">int</span><br><span class="hljs-keyword">var</span> i <span class="hljs-keyword">int</span> = <span class="hljs-number">1</span><br><span class="hljs-keyword">var</span> j MyInt = i<br></code></pre></td></tr></table></figure>
<ol start="2" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs GO"><span class="hljs-keyword">type</span> MyInt <span class="hljs-keyword">int</span><br><span class="hljs-keyword">var</span> i <span class="hljs-keyword">int</span> = <span class="hljs-number">1</span><br><span class="hljs-keyword">var</span> j MyInt = (MyInt)i<br></code></pre></td></tr></table></figure>
<ol start="3" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> MyInt <span class="hljs-keyword">int</span><br><span class="hljs-keyword">var</span> i <span class="hljs-keyword">int</span> = <span class="hljs-number">1</span><br><span class="hljs-keyword">var</span> j MyInt = MyInt(i)<br></code></pre></td></tr></table></figure>
<ol start="4" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> MyInt <span class="hljs-keyword">int</span><br><span class="hljs-keyword">var</span> i <span class="hljs-keyword">int</span> = <span class="hljs-number">1</span><br><span class="hljs-keyword">var</span> j MyInt = i.(MyInt)   <span class="hljs-comment">// Invalid type assertion: i.(MyInt) (non-interface type int on left)</span><br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>C</p>

    </div>
</div>
<p>11.关于局部变量的初始化，下面正确的使用方式是（）</p>
<p>A. var i int = 10</p>
<p>B. var i = 10</p>
<p>C. i := 10</p>
<p>D. i = 10</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABC</p>

    </div>
</div>
<p>12.关于const常量定义，下面正确的使用方式是（）</p>
<ol type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">const</span> Pi <span class="hljs-keyword">float64</span> = <span class="hljs-number">3.14159265358979323846</span><br><span class="hljs-keyword">const</span> zero = <span class="hljs-number">0.0</span><br></code></pre></td></tr></table></figure>
<ol start="2" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">const</span> (<br>        size <span class="hljs-keyword">int64</span> = <span class="hljs-number">1024</span><br>        eof = <span class="hljs-number">-1</span><br>)<br></code></pre></td></tr></table></figure>
<ol start="3" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">const</span> (<br>        ERR_ELEM_EXIST error = errors.New(<span class="hljs-string">&quot;element already exists&quot;</span>)<br>        ERR_ELEM_NT_EXIST error = errors.New(<span class="hljs-string">&quot;element not exists&quot;</span>)<br>) <span class="hljs-comment">// Const initializer &#x27;errors.New(&quot;element already exists&quot;)&#x27; is not a constant</span><br></code></pre></td></tr></table></figure>
<ol start="4" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">const</span> u, v <span class="hljs-keyword">float32</span> = <span class="hljs-number">0</span>, <span class="hljs-number">3</span><br><span class="hljs-keyword">const</span> a, b, c = <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-string">&quot;foo&quot;</span><br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABD</p>

    </div>
</div>
<p>13.关于布尔变量b的赋值，下面错误的用法是（）</p>
<p>A. <code>b = true</code></p>
<p>B. <code>b = 1     //  Cannot use '1' (type untyped int) as type bool in assignment</code></p>
<p>C. <code>b = bool(1)   //Cannot convert expression of type int to type bool</code></p>
<p>D. <code>b = (1 == 2)</code></p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BC</p>

    </div>
</div>
<p>14.下面的程序的运行结果是（）</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>        <span class="hljs-keyword">if</span> (<span class="hljs-literal">true</span>) &#123;<br>            <span class="hljs-keyword">defer</span> fmt.Printf(<span class="hljs-string">&quot;1&quot;</span>)<br>        &#125; <span class="hljs-keyword">else</span> &#123;<br>            <span class="hljs-keyword">defer</span> fmt.Printf(<span class="hljs-string">&quot;2&quot;</span>)<br>        &#125;<br>        fmt.Printf(<span class="hljs-string">&quot;3&quot;</span>)<br>&#125;<br></code></pre></td></tr></table></figure>
<p>A. 321</p>
<p>B. 32</p>
<p>C. 31</p>
<p>D. 13</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>C</p>

    </div>
</div>
<p>15.关于switch语句，下面说法正确的有（）</p>
<p>A. 条件表达式必须为常量或者整数</p>
<p>B. 单个case中，可以出现多个结果选项</p>
<p>C. 需要用break来明确退出一个case</p>
<p>D. 只有在case中明确添加fallthrough关键字，才会继续执行紧跟的下一个case</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BD</p>

    </div>
</div>
<p>16.golang中没有隐藏的this指针，这句话的含义是（）</p>
<p>A. 方法施加的对象显式传递，没有被隐藏起来</p>
<p>B. golang沿袭了传统面向对象编程中的诸多概念，比如继承、虚函数和构造函数</p>
<p>C. golang的面向对象表达更直观，对于面向过程只是换了一种语法形式来表达</p>
<p>D. 方法施加的对象不需要非得是指针，也不用非得叫this</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ACD</p>

    </div>
</div>
<p>17.golang中的引用类型包括（）</p>
<p>A. 数组切片</p>
<p>B. map</p>
<p>C. channel</p>
<p>D. interface</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABCD</p>

    </div>
</div>
<p>18.golang中的指针运算包括（）</p>
<p>A. 可以对指针进行自增或自减运算</p>
<p>B. 可以通过“&amp;”取指针的地址</p>
<p>C. 可以通过“*”取指针指向的数据</p>
<p>D. 可以对指针进行下标运算</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BC</p>

    </div>
</div>
<p>19.关于main函数（可执行程序的执行起点），下面说法正确的是（）</p>
<p>A. main函数不能带参数</p>
<p>B. main函数不能定义返回值</p>
<p>C. main函数所在的包必须为main包</p>
<p>D. main函数中可以使用flag包来获取和解析命令行参数</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABCD</p>

    </div>
</div>
<p>20.下面赋值正确的是（）</p>
<p>A. var x = nil</p>
<p>B. var x interface{} = nil</p>
<p>C. var x string = nil</p>
<p>D. var x error = nil</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BD</p>

    </div>
</div>
<p>21.关于整型切片的初始化，下面正确的是（）</p>
<p>A. s := make([]int)</p>
<p>B. s := make([]int, 0)</p>
<p>C. s := make([]int, 5, 10)</p>
<p>D. s := []int{1, 2, 3, 4, 5}</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BCD</p>

    </div>
</div>
<p>22.从切片中删除一个元素，下面的算法实现正确的是（）</p>
<ol type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *Slice)</span><span class="hljs-title">Remove</span><span class="hljs-params">(value <span class="hljs-keyword">interface</span>&#123;&#125;)</span> <span class="hljs-title">error</span></span> &#123;<br>        <span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> *s &#123;<br>            <span class="hljs-keyword">if</span> isEqual(value, v) &#123;<br>                <span class="hljs-keyword">if</span> i== <span class="hljs-built_in">len</span>(*s) - <span class="hljs-number">1</span> &#123;<br>                    *s = (*s)[:i]<br>                &#125;<span class="hljs-keyword">else</span> &#123;<br>                    *s = <span class="hljs-built_in">append</span>((*s)[:i],(*s)[i + <span class="hljs-number">2</span>:]...)<br>                &#125;<br>                <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>            &#125;<br>        &#125;<br>        <span class="hljs-keyword">return</span> ERR_ELEM_NT_EXIST<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="2" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *Slice)</span><span class="hljs-title">Remove</span><span class="hljs-params">(value <span class="hljs-keyword">interface</span>&#123;&#125;)</span> <span class="hljs-title">error</span></span> &#123;<br>        <span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> *s &#123;<br>            <span class="hljs-keyword">if</span> isEqual(value, v) &#123;<br>                *s = <span class="hljs-built_in">append</span>((*s)[:i],(*s)[i + <span class="hljs-number">1</span>:])<br>                <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>            &#125;<br>        &#125;<br>        <span class="hljs-keyword">return</span> ERR_ELEM_NT_EXIST<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="3" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *Slice)</span><span class="hljs-title">Remove</span><span class="hljs-params">(value <span class="hljs-keyword">interface</span>&#123;&#125;)</span> <span class="hljs-title">error</span></span> &#123;<br>        <span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> *s &#123;<br>            <span class="hljs-keyword">if</span> isEqual(value, v) &#123;<br>                <span class="hljs-built_in">delete</span>(*s, v)<br>                <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>            &#125;<br>        &#125;<br>        <span class="hljs-keyword">return</span> ERR_ELEM_NT_EXIST<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="4" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(s *Slice)</span><span class="hljs-title">Remove</span><span class="hljs-params">(value <span class="hljs-keyword">interface</span>&#123;&#125;)</span> <span class="hljs-title">error</span></span> &#123;<br>        <span class="hljs-keyword">for</span> i, v := <span class="hljs-keyword">range</span> *s &#123;<br>            <span class="hljs-keyword">if</span> isEqual(value, v) &#123;<br>                *s = <span class="hljs-built_in">append</span>((*s)[:i],(*s)[i + <span class="hljs-number">1</span>:]...)<br>                <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>            &#125;<br>        &#125;<br>        <span class="hljs-keyword">return</span> ERR_ELEM_NT_EXIST<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>D</p>

    </div>
</div>
<p>23.关于变量的自增和自减操作，下面语句正确的是（）</p>
<ol type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go">i := <span class="hljs-number">1</span><br>i++<br></code></pre></td></tr></table></figure>
<ol start="2" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go">i := <span class="hljs-number">1</span><br>j = i++      <span class="hljs-comment">// &#x27;,&#x27;, &#x27;;&#x27;, new line or &#x27;&#125;&#x27; expected, got &#x27;++&#x27;</span><br></code></pre></td></tr></table></figure>
<ol start="3" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go">i := <span class="hljs-number">1</span><br>++i<br></code></pre></td></tr></table></figure>
<ol start="4" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs go">i := <span class="hljs-number">1</span><br>i--<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AD</p>

    </div>
</div>
<p>24.关于函数声明，下面语法错误的是（）</p>
<p>A. func f(a, b int) (value int, err error)</p>
<p>B. func f(a int, b int) (value int, err error)</p>
<p>C. func f(a, b int) (value int, error)</p>
<p>D. func f(a int, b int) (int, int, error)</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>C</p>

    </div>
</div>
<p>25.如果Add函数的调用代码为：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>    <span class="hljs-keyword">var</span> a Integer = <span class="hljs-number">1</span><br>    <span class="hljs-keyword">var</span> b Integer = <span class="hljs-number">2</span><br>    <span class="hljs-keyword">var</span> i <span class="hljs-keyword">interface</span>&#123;&#125; = &amp;a<br>    sum := i.(*Integer).Add(b)<br>    fmt.Println(sum)<br>&#125;<br></code></pre></td></tr></table></figure>
<p>则Add函数定义正确的是（）</p>
<ol type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> a + b<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="2" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b *Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> a + *b<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="3" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a *Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> *a + b<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="4" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a *Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b *Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> *a + *b<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AC</p>

    </div>
</div>
<p>26.如果Add函数的调用代码为：</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> &#123;<br>        <span class="hljs-keyword">var</span> a Integer = <span class="hljs-number">1</span><br>        <span class="hljs-keyword">var</span> b Integer = <span class="hljs-number">2</span><br>        <span class="hljs-keyword">var</span> i <span class="hljs-keyword">interface</span>&#123;&#125; = a<br>        sum := i.(Integer).Add(b)<br>        fmt.Println(sum)<br>&#125;<br></code></pre></td></tr></table></figure>
<p>则Add函数定义正确的是（）</p>
<ol type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> a + b<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="2" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b *Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> a + *b<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="3" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a *Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> *a + b<br>&#125;<br></code></pre></td></tr></table></figure>
<ol start="4" type="A">
<li></li>
</ol>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Integer <span class="hljs-keyword">int</span><br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(a *Integer)</span> <span class="hljs-title">Add</span><span class="hljs-params">(b *Integer)</span> <span class="hljs-title">Integer</span></span> &#123;<br>        <span class="hljs-keyword">return</span> *a + *b<br>&#125;<br></code></pre></td></tr></table></figure>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AC</p>

    </div>
</div>
<p>27.关于GetPodAction定义，下面赋值正确的是（）</p>
<figure class="highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs go"><span class="hljs-keyword">type</span> Fragment <span class="hljs-keyword">interface</span> &#123;<br>        Exec(transInfo *TransInfo) error<br>&#125;<br><span class="hljs-keyword">type</span> GetPodAction <span class="hljs-keyword">struct</span> &#123;<br>&#125;<br><span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-params">(g GetPodAction)</span> <span class="hljs-title">Exec</span><span class="hljs-params">(transInfo *TransInfo)</span> <span class="hljs-title">error</span></span> &#123;<br>        ...<br>        <span class="hljs-keyword">return</span> <span class="hljs-literal">nil</span><br>&#125;<br></code></pre></td></tr></table></figure>
<p>A. var fragment Fragment = new(GetPodAction)</p>
<p>B. var fragment Fragment = GetPodAction</p>
<p>C. var fragment Fragment = &amp;GetPodAction{}</p>
<p>D. var fragment Fragment = GetPodAction{}</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ACD</p>

    </div>
</div>
<p>28.关于GoMock，下面说法正确的是（）</p>
<p>A. GoMock可以对interface打桩</p>
<p>B. GoMock可以对类的成员函数打桩</p>
<p>C. GoMock可以对函数打桩</p>
<p>D. GoMock打桩后的依赖注入可以通过GoStub完成</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AD</p>

    </div>
</div>
<p>29.关于接口，下面说法正确的是（）</p>
<p>A. 只要两个接口拥有相同的方法列表（次序不同不要紧），那么它们就是等价的，可以相互赋值</p>
<p>B. 如果接口A的方法列表是接口B的方法列表的子集，那么接口B可以赋值给接口A</p>
<p>C. 接口查询是否成功，要在运行期才能够确定</p>
<p>D. 接口赋值是否可行，要在运行期才能够确定</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABC</p>

    </div>
</div>
<p>30.关于channel，下面语法正确的是（）</p>
<p>A. var ch chan int</p>
<p>B. ch := make(chan int)</p>
<p>C. &lt;- ch</p>
<p>D. ch &lt;-</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABC</p>

    </div>
</div>
<p>31.关于同步锁，下面说法正确的是（）</p>
<p>A. 当一个goroutine获得了Mutex后，其他goroutine就只能乖乖的等待，除非该goroutine释放这个Mutex</p>
<p>B. RWMutex在读锁占用的情况下，会阻止写，但不阻止读</p>
<p>C. RWMutex在写锁占用情况下，会阻止任何其他goroutine（无论读和写）进来，整个锁相当于由该goroutine独占</p>
<p>D. Lock()操作需要保证有Unlock()或RUnlock()调用与之对应</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABC</p>

    </div>
</div>
<p>32.golang中大多数数据类型都可以转化为有效的JSON文本，下面几种类型除外（）</p>
<p>A. 指针</p>
<p>B. channel</p>
<p>C. complex</p>
<p>D. 函数</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BCD</p>

    </div>
</div>
<p>33.关于go vendor，下面说法正确的是（）</p>
<p>A. 基本思路是将引用的外部包的源代码放在当前工程的vendor目录下面</p>
<p>B. 编译go代码会优先从vendor目录先寻找依赖包</p>
<p>C. 可以指定引用某个特定版本的外部包</p>
<p>D. 有了vendor目录后，打包当前的工程代码到其他机器的$GOPATH/src下都可以通过编译</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>ABD</p>

    </div>
</div>
<p>34.flag是bool型变量，下面if表达式符合编码规范的是（）</p>
<p>A. if flag == 1</p>
<p>B. if flag</p>
<p>C. if flag == false</p>
<p>D. if !flag</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>BD</p>

    </div>
</div>
<p>35.value是整型变量，下面if表达式符合编码规范的是（）</p>
<p>A. if value == 0</p>
<p>B. if value</p>
<p>C. if value != 0</p>
<p>D. if !value</p>
<div class="spoiler collapsed">
    <div class="spoiler-title">
        答案
    </div>
    <div class="spoiler-content">
        <p>AC</p>

    </div>
</div>
<p><a target="_blank" rel="noopener" href="https://www.kancloud.cn/yanshandou/kam2/598850">流程图</a></p>
<script type="text&#x2F;javascript" src="https://cdn.jsdelivr.net/npm/kity@2.0.4/dist/kity.min.js"></script><script type="text&#x2F;javascript" src="https://cdn.jsdelivr.net/npm/kityminder-core@1.4.50/dist/kityminder.core.min.js"></script><script defer="true" type="text&#x2F;javascript" src="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.7.0/dist/mindmap.min.js"></script><link rel="stylesheet" type="text&#x2F;css" href="https://cdn.jsdelivr.net/npm/hexo-simple-mindmap@0.7.0/dist/mindmap.min.css"><link rel="stylesheet" href="/css/spoiler.css" type="text/css"><script src="/js/spoiler.js" type="text/javascript" async></script>
                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/Golang/" class="category-chain-item">Golang</a>
  
  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/Go/">#Go</a>
      
        <a href="/tags/ADT/">#ADT</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>【Go】学习笔记</div>
      <div>https://weitrue.github.io/2021/02/07/golang/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div><NAME></div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2021年2月7日</div>
        </div>
      
      
      
        <div class="license-meta-item">
          <div>许可协议</div>
          <div>
            
              
              
                <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
                  <span class="hint--top hint--rounded" aria-label="BY - 署名">
                    <i class="iconfont icon-by"></i>
                  </span>
                </a>
              
            
          </div>
        </div>
      
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2021/03/05/lt-linkedList/" title="【LeetCode】线性表相关问题">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">【LeetCode】线性表相关问题</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2021/01/11/ml/" title="【ML】机器学习概述与简单应用">
                        <span class="hidden-mobile">【ML】机器学习概述与简单应用</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header">
    <i class="iconfont icon-list"></i>
    <span>目录</span>
  </p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  


  
  





  <script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/mermaid@8/dist/mermaid.min.js', function() {
    mermaid.initialize({"theme":"default"});

    Fluid.events.registerRefreshCallback(function() {
      if ('mermaid' in window) {
        mermaid.init();
      }
    });
  });
</script>






    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="#" target="_blank" rel="nofollow noopener"><span>Wei</span></a> <i class="iconfont icon-love"></i> <a href="#" target="_blank" rel="nofollow noopener"><span>Trable</span></a> <div style="font-size: 0.85rem"> <span id="timeDate">载入天数...</span> <span id="times">载入时分秒...</span> <script src="/cus_js/duration.js"></script> </div> 
    </div>
  
  
    <div class="statistics">
  
  

  
    
      <span id="busuanzi_container_site_pv" style="display: none">
        总访问量 
        <span id="busuanzi_value_site_pv"></span>
         次
      </span>
    
    
      <span id="busuanzi_container_site_uv" style="display: none">
        总访客数 
        <span id="busuanzi_value_site_uv"></span>
         人
      </span>
    
    
  
</div>

  
  
    <!-- 备案信息 ICP for China -->
    <div class="beian">
  <span>
    <a href="http://beian.miit.gov.cn/" target="_blank" rel="nofollow noopener">
      杭ICP证123456号
    </a>
  </span>
  
    
      <span>
        <a
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=12345678"
          rel="nofollow noopener"
          class="beian-police"
          target="_blank"
        >
          
            <span style="visibility: hidden; width: 0">|</span>
            <img src="/images/img/police_beian.png" srcset="/img/loading.gif" lazyload alt="police-icon"/>
          
          <span>杭公网安备12345678号</span>
        </a>
      </span>
    
  
</div>

  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nprogress@0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js" ></script>
<script  src="https://cdn.jsdelivr.net/npm/bootstrap@4/dist/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://cdn.jsdelivr.net/npm/typed.js@2/lib/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/tocbot@4/dist/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init(Object.assign({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      scrollSmooth    : true,
      includeTitleTags: true,
      headingsOffset  : -boardTop,
    }, CONFIG.toc));
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }

    Fluid.events.registerRefreshCallback(function() {
      if ('tocbot' in window) {
        tocbot.refresh();
        var toc = jQuery('#toc');
        if (toc.length === 0 || !tocbot) {
          return;
        }
        if (toc.find('.toc-list-item').length > 0) {
          toc.css('visibility', 'visible');
        }
      }
    });
  });
</script>


  <script src=https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/anchor-js@4/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));

    Fluid.events.registerRefreshCallback(function() {
      if ('anchors' in window) {
        anchors.removeAll();
        var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
        var res = [];
        for (var item of el) {
          res.push('.markdown-body > ' + item.trim());
        }
        if (CONFIG.anchorjs.placement === 'left') {
          anchors.options.class = 'anchorjs-link-left';
        }
        anchors.add(res.join(', '));
      }
    });
  });
</script>


  
<script>
  Fluid.utils.createScript('https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3/dist/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  
      <script>
        if (!window.MathJax) {
          window.MathJax = {
            tex    : {
              inlineMath: { '[+]': [['$', '$']] }
            },
            loader : {
              load: ['ui/lazy']
            },
            options: {
              renderActions: {
                insertedScript: [200, () => {
                  document.querySelectorAll('mjx-container').forEach(node => {
                    let target = node.parentNode;
                    if (target.nodeName.toLowerCase() === 'li') {
                      target.parentNode.classList.add('has-jax');
                    }
                  });
                }, '', false]
              }
            }
          };
        } else {
          MathJax.startup.document.state(0);
          MathJax.texReset();
          MathJax.typeset();
          MathJax.typesetPromise();
        }

        Fluid.events.registerRefreshCallback(function() {
          if ('MathJax' in window && MathJax.startup.document && typeof MathJax.startup.document.state === 'function') {
            MathJax.startup.document.state(0);
            MathJax.texReset();
            MathJax.typeset();
            MathJax.typesetPromise();
          }
        });
      </script>
    

  <script  src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" ></script>

  <script  src="/js/local-search.js" ></script>

  <script defer src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body>
</html>
