<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Go on Allens' Blog</title><link>https://allens.tech/tags/go/</link><description>Recent content from Allens' Blog</description><generator>Hugo</generator><language>en-us</language><managingEditor>allens.leng@gmail.com (Allens)</managingEditor><webMaster>allens.leng@gmail.com (Allens)</webMaster><copyright>All articles on this blog are licensed under the BY-NC-SA license agreement unless otherwise stated. Please indicate the source when reprinting!</copyright><lastBuildDate>Tue, 08 Aug 2023 21:00:00 +0800</lastBuildDate><atom:link href="https://allens.tech/tags/go/index.xml" rel="self" type="application/rss+xml"/><item><title>学习笔记 - gorm + mysql 使用小知识及避坑指南</title><link>https://allens.tech/post/202308082100/</link><pubDate>Tue, 08 Aug 2023 21:00:00 +0800</pubDate><author>allens.leng@gmail.com (Allens)</author><guid>https://allens.tech/post/202308082100/</guid><description>
<![CDATA[<h1>学习笔记 - gorm + mysql 使用小知识及避坑指南</h1><p>Author: Allens(allens.leng@gmail.com)</p>
        
          <h2 id="描述">
<a class="header-anchor" href="#%e6%8f%8f%e8%bf%b0"></a>
描述
</h2><p>作为一个 gorm 的重度使用者，在习惯了 gorm 带来的便利，也遇到了很多的问题，日前看到一些小伙伴仍然会因为对 gorm 特性的不了解，导致出现 panic 或者数据的错误更新的问题，所以这边提供一些小技巧和避坑指南，持续更新&hellip;</p>
<h2 id="插入">
<a class="header-anchor" href="#%e6%8f%92%e5%85%a5"></a>
插入
</h2><h3 id="gorm-解决并发插入报错">
<a class="header-anchor" href="#gorm-%e8%a7%a3%e5%86%b3%e5%b9%b6%e5%8f%91%e6%8f%92%e5%85%a5%e6%8a%a5%e9%94%99"></a>
gorm 解决并发插入报错
</h3><p>当你有并发插入的情况，就难免会出现数据冲突的问题，如果不做处理的话，会出现报错 <code>Duplicate key</code>，gorm 提供了中间件来解决这个问题。</p>
<p>如果你期望 upsert：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#a6e22e">doc</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">model</span>.<span style="color:#a6e22e">Table</span>{<span style="color:#a6e22e">Title</span>: <span style="color:#e6db74">&#34;table&#34;</span>}
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Table</span>(<span style="color:#e6db74">&#34;table&#34;</span>).<span style="color:#a6e22e">Clauses</span>(<span style="color:#a6e22e">clause</span>.<span style="color:#a6e22e">OnConflict</span>{<span style="color:#a6e22e">UpdateAll</span>: <span style="color:#66d9ef">true</span>}).<span style="color:#a6e22e">Create</span>(<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">doc</span>).<span style="color:#a6e22e">Error</span>
</span></span></code></pre></div><p>你也可以根据实际使用场景选择其他不同的冲突处理方案：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">OnConflict</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Columns</span>      []<span style="color:#a6e22e">Column</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Where</span>        <span style="color:#a6e22e">Where</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">TargetWhere</span>  <span style="color:#a6e22e">Where</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">OnConstraint</span> <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">DoNothing</span>    <span style="color:#66d9ef">bool</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">DoUpdates</span>    <span style="color:#a6e22e">Set</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">UpdateAll</span>    <span style="color:#66d9ef">bool</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h3 id="clauses-on-conflict-do-nothing-带来的问题">
<a class="header-anchor" href="#clauses-on-conflict-do-nothing-%e5%b8%a6%e6%9d%a5%e7%9a%84%e9%97%ae%e9%a2%98"></a>
Clauses on conflict do nothing 带来的问题
</h3><p>如果你和我一样习惯用结构体指针插入，那么如果用 Clauses OnConflict do nothing 解决冲突的同时可能会带来另外一个问题，那就是数据不冲突时，insert id 会回写，但是冲突之后不会进行回写。</p>
<p>部分源码如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> !<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">DryRun</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Error</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">result</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ConnPool</span>.<span style="color:#a6e22e">ExecContext</span>(<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">SQL</span>.<span style="color:#a6e22e">String</span>(), <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Vars</span><span style="color:#f92672">...</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">RowsAffected</span>, <span style="color:#a6e22e">_</span> = <span style="color:#a6e22e">result</span>.<span style="color:#a6e22e">RowsAffected</span>()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">RowsAffected</span> &gt; <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">HasDefaultValue</span> {
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">insertID</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">result</span>.<span style="color:#a6e22e">LastInsertId</span>(); <span style="color:#a6e22e">err</span> <span style="color:#f92672">==</span> <span style="color:#66d9ef">nil</span> <span style="color:#f92672">&amp;&amp;</span> <span style="color:#a6e22e">insertID</span> &gt; <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>					<span style="color:#66d9ef">switch</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ReflectValue</span>.<span style="color:#a6e22e">Kind</span>() {
</span></span><span style="display:flex;"><span>					<span style="color:#66d9ef">case</span> <span style="color:#a6e22e">reflect</span>.<span style="color:#a6e22e">Slice</span>, <span style="color:#a6e22e">reflect</span>.<span style="color:#a6e22e">Array</span>:
</span></span><span style="display:flex;"><span>						<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">LastInsertIDReversed</span> {
</span></span><span style="display:flex;"><span>							<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ReflectValue</span>.<span style="color:#a6e22e">Len</span>() <span style="color:#f92672">-</span> <span style="color:#ae81ff">1</span>; <span style="color:#a6e22e">i</span> <span style="color:#f92672">&gt;=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span><span style="color:#f92672">--</span> {
</span></span><span style="display:flex;"><span>								<span style="color:#a6e22e">rv</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ReflectValue</span>.<span style="color:#a6e22e">Index</span>(<span style="color:#a6e22e">i</span>)
</span></span><span style="display:flex;"><span>								<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">reflect</span>.<span style="color:#a6e22e">Indirect</span>(<span style="color:#a6e22e">rv</span>).<span style="color:#a6e22e">Kind</span>() <span style="color:#f92672">!=</span> <span style="color:#a6e22e">reflect</span>.<span style="color:#a6e22e">Struct</span> {
</span></span><span style="display:flex;"><span>									<span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>								}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>								<span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">isZero</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">ValueOf</span>(<span style="color:#a6e22e">rv</span>)
</span></span><span style="display:flex;"><span>								<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">isZero</span> {
</span></span><span style="display:flex;"><span>									<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">Set</span>(<span style="color:#a6e22e">rv</span>, <span style="color:#a6e22e">insertID</span>)
</span></span><span style="display:flex;"><span>									<span style="color:#a6e22e">insertID</span> <span style="color:#f92672">-=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">AutoIncrementIncrement</span>
</span></span><span style="display:flex;"><span>								}
</span></span><span style="display:flex;"><span>							}
</span></span><span style="display:flex;"><span>						} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>							<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">i</span> <span style="color:#f92672">:=</span> <span style="color:#ae81ff">0</span>; <span style="color:#a6e22e">i</span> &lt; <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ReflectValue</span>.<span style="color:#a6e22e">Len</span>(); <span style="color:#a6e22e">i</span><span style="color:#f92672">++</span> {
</span></span><span style="display:flex;"><span>								<span style="color:#a6e22e">rv</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ReflectValue</span>.<span style="color:#a6e22e">Index</span>(<span style="color:#a6e22e">i</span>)
</span></span><span style="display:flex;"><span>								<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">reflect</span>.<span style="color:#a6e22e">Indirect</span>(<span style="color:#a6e22e">rv</span>).<span style="color:#a6e22e">Kind</span>() <span style="color:#f92672">!=</span> <span style="color:#a6e22e">reflect</span>.<span style="color:#a6e22e">Struct</span> {
</span></span><span style="display:flex;"><span>									<span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>								}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>								<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">isZero</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">ValueOf</span>(<span style="color:#a6e22e">rv</span>); <span style="color:#a6e22e">isZero</span> {
</span></span><span style="display:flex;"><span>									<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">Set</span>(<span style="color:#a6e22e">rv</span>, <span style="color:#a6e22e">insertID</span>)
</span></span><span style="display:flex;"><span>									<span style="color:#a6e22e">insertID</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">AutoIncrementIncrement</span>
</span></span><span style="display:flex;"><span>								}
</span></span><span style="display:flex;"><span>							}
</span></span><span style="display:flex;"><span>						}
</span></span><span style="display:flex;"><span>					<span style="color:#66d9ef">case</span> <span style="color:#a6e22e">reflect</span>.<span style="color:#a6e22e">Struct</span>:
</span></span><span style="display:flex;"><span>						<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">isZero</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">ValueOf</span>(<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ReflectValue</span>); <span style="color:#a6e22e">isZero</span> {
</span></span><span style="display:flex;"><span>							<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">Schema</span>.<span style="color:#a6e22e">PrioritizedPrimaryField</span>.<span style="color:#a6e22e">Set</span>(<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">Statement</span>.<span style="color:#a6e22e">ReflectValue</span>, <span style="color:#a6e22e">insertID</span>)
</span></span><span style="display:flex;"><span>						}
</span></span><span style="display:flex;"><span>					}
</span></span><span style="display:flex;"><span>				} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">AddError</span>(<span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>				}
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	} <span style="color:#66d9ef">else</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">db</span>.<span style="color:#a6e22e">AddError</span>(<span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>大概意思就是，如果影响行数 &gt; 1 才会进行 insert id 赋值，也就是说，如果此时直接使用 doc 中的 id，那么这个 id 的值会是 0。</p>
        
        <hr><p>Published on 2023-08-08 at <a href='https://allens.tech/'>Allens' Blog</a>, last modified on 2023-08-08</p>]]></description><category>学习笔记</category></item><item><title>Cursor - 人工智能编写代码的强大之处</title><link>https://allens.tech/post/202304272007/</link><pubDate>Thu, 27 Apr 2023 20:07:03 +0800</pubDate><author>allens.leng@gmail.com (Allens)</author><guid>https://allens.tech/post/202304272007/</guid><description>
<![CDATA[<h1>Cursor - 人工智能编写代码的强大之处</h1><p>Author: Allens(allens.leng@gmail.com)</p>
        
          <h2 id="描述">
<a class="header-anchor" href="#%e6%8f%8f%e8%bf%b0"></a>
描述
</h2><p>最近需要写一个告警的功能，本来是打算自己实现 metric 和 alert，但是由于我们本来就已经有 grafana 和 prometheus 了，就想要借助成熟体系来实现，这样可以节省很多工作，但是找了一些库，都没有合适的姿势入场，最近主管推给我一个软件 <a href="https://www.cursor.so/">Cursor</a>，来试一下。</p>
<h3 id="使用">
<a class="header-anchor" href="#%e4%bd%bf%e7%94%a8"></a>
使用
</h3><ul>
<li>先来看下主界面
<img src="/img/2023-04-27/1.png" alt=""></li>
<li>command + k
<img src="/img/2023-04-27/2.png" alt=""></li>
<li>来试一下
<img src="/img/2023-04-27/3.png" alt=""></li>
<li>效果
<img src="/img/2023-04-27/4.png" alt=""></li>
<li>很好，但是好像没有鉴权 [ command + a &amp; command + k ]
<img src="/img/2023-04-27/5.png" alt=""></li>
<li>ok，文件太长就不截图了</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Import necessary packages</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;context&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;crypto/tls&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;net&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;time&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;github.com/prometheus/client_golang/api&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">v1</span> <span style="color:#e6db74">&#34;github.com/prometheus/client_golang/api/prometheus/v1&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;github.com/prometheus/common/model&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// BasicAuthRoundTripper is a RoundTripper that adds basic authentication credentials to requests</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">BasicAuthRoundTripper</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Username</span>     <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Password</span>     <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">RoundTripper</span> <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">RoundTripper</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">rt</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">BasicAuthRoundTripper</span>) <span style="color:#a6e22e">RoundTrip</span>(<span style="color:#a6e22e">req</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Request</span>) (<span style="color:#f92672">*</span><span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Response</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">SetBasicAuth</span>(<span style="color:#a6e22e">rt</span>.<span style="color:#a6e22e">Username</span>, <span style="color:#a6e22e">rt</span>.<span style="color:#a6e22e">Password</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">rt</span>.<span style="color:#a6e22e">RoundTripper</span>.<span style="color:#a6e22e">RoundTrip</span>(<span style="color:#a6e22e">req</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Define a struct to hold the query results</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">QueryResult</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Metric</span> <span style="color:#a6e22e">model</span>.<span style="color:#a6e22e">Metric</span>      <span style="color:#e6db74">`json:&#34;metric&#34;`</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Value</span>  <span style="color:#a6e22e">model</span>.<span style="color:#a6e22e">SampleValue</span> <span style="color:#e6db74">`json:&#34;value&#34;`</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Define a function to query Prometheus with a given username, password</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">QueryPrometheus</span>(<span style="color:#a6e22e">username</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">password</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">query</span> <span style="color:#66d9ef">string</span>) ([]<span style="color:#a6e22e">QueryResult</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Create a new HTTP client with the given username and password</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">client</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">NewClient</span>(<span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Config</span>{
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">Address</span>: <span style="color:#e6db74">&#34;http://localhost:9090&#34;</span>,
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">RoundTripper</span>: <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">BasicAuthRoundTripper</span>{
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Username</span>: <span style="color:#a6e22e">username</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Password</span>: <span style="color:#a6e22e">password</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">RoundTripper</span>: <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Transport</span>{
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">Proxy</span>:           <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">ProxyFromEnvironment</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">TLSClientConfig</span>: <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">tls</span>.<span style="color:#a6e22e">Config</span>{<span style="color:#a6e22e">InsecureSkipVerify</span>: <span style="color:#66d9ef">true</span>},
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// Set the username and password for basic authentication</span>
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// Note: this is not secure and should not be used in production</span>
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// Instead, use a secure authentication method such as OAuth2</span>
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// or a reverse proxy with authentication</span>
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">DialContext</span>: (<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">net</span>.<span style="color:#a6e22e">Dialer</span>{
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">Timeout</span>:   <span style="color:#ae81ff">30</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">KeepAlive</span>: <span style="color:#ae81ff">30</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				}).<span style="color:#a6e22e">DialContext</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">ForceAttemptHTTP2</span>:     <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">MaxIdleConns</span>:          <span style="color:#ae81ff">100</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">IdleConnTimeout</span>:       <span style="color:#ae81ff">90</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">TLSHandshakeTimeout</span>:   <span style="color:#ae81ff">10</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">ExpectContinueTimeout</span>: <span style="color:#ae81ff">1</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">ProxyConnectHeader</span>:    <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Header</span>{},
</span></span><span style="display:flex;"><span>			},
</span></span><span style="display:flex;"><span>		},
</span></span><span style="display:flex;"><span>	})
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Create a new Prometheus API client</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">prometheusClient</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">v1</span>.<span style="color:#a6e22e">NewAPI</span>(<span style="color:#a6e22e">client</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Query Prometheus with the built query string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">result</span>, <span style="color:#a6e22e">warnings</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">prometheusClient</span>.<span style="color:#a6e22e">Query</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Background</span>(), <span style="color:#a6e22e">query</span>, <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Now</span>())
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">warnings</span>) &gt; <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">&#34;Warnings:&#34;</span>, <span style="color:#a6e22e">warnings</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Parse the query result into a slice of QueryResult structs</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">queryResults</span> []<span style="color:#a6e22e">QueryResult</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">res</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">result</span>.(<span style="color:#a6e22e">model</span>.<span style="color:#a6e22e">Vector</span>) {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">queryResults</span> = append(<span style="color:#a6e22e">queryResults</span>, <span style="color:#a6e22e">QueryResult</span>{
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Metric</span>: <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">Metric</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Value</span>:  <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">Value</span>,
</span></span><span style="display:flex;"><span>		})
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">queryResults</span>, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><ul>
<li>感觉还是不够，如果能按照 label 查询就更好了。
<img src="/img/2023-04-27/6.png" alt=""></li>
<li>结果如下</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Import necessary packages</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;context&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;crypto/tls&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;fmt&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;net&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;net/http&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;time&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;github.com/prometheus/client_golang/api&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">v1</span> <span style="color:#e6db74">&#34;github.com/prometheus/client_golang/api/prometheus/v1&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;github.com/prometheus/common/model&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// BasicAuthRoundTripper is a RoundTripper that adds basic authentication credentials to requests</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">BasicAuthRoundTripper</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Username</span>     <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Password</span>     <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">RoundTripper</span> <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">RoundTripper</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> (<span style="color:#a6e22e">rt</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">BasicAuthRoundTripper</span>) <span style="color:#a6e22e">RoundTrip</span>(<span style="color:#a6e22e">req</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Request</span>) (<span style="color:#f92672">*</span><span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Response</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">SetBasicAuth</span>(<span style="color:#a6e22e">rt</span>.<span style="color:#a6e22e">Username</span>, <span style="color:#a6e22e">rt</span>.<span style="color:#a6e22e">Password</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">rt</span>.<span style="color:#a6e22e">RoundTripper</span>.<span style="color:#a6e22e">RoundTrip</span>(<span style="color:#a6e22e">req</span>)
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Define a struct to hold the query results</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">QueryResult</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Metric</span> <span style="color:#a6e22e">model</span>.<span style="color:#a6e22e">Metric</span>      <span style="color:#e6db74">`json:&#34;metric&#34;`</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Value</span>  <span style="color:#a6e22e">model</span>.<span style="color:#a6e22e">SampleValue</span> <span style="color:#e6db74">`json:&#34;value&#34;`</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Define a function to query Prometheus with a given username, password, and label</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">QueryPrometheus</span>(<span style="color:#a6e22e">username</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">password</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">my_metric</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">key</span> <span style="color:#66d9ef">string</span>, <span style="color:#a6e22e">value</span> <span style="color:#66d9ef">string</span>) ([]<span style="color:#a6e22e">QueryResult</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Create a new HTTP client with the given username and password</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">client</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">NewClient</span>(<span style="color:#a6e22e">api</span>.<span style="color:#a6e22e">Config</span>{
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">Address</span>: <span style="color:#e6db74">&#34;http://localhost:9090&#34;</span>,
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">RoundTripper</span>: <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">BasicAuthRoundTripper</span>{
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Username</span>: <span style="color:#a6e22e">username</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Password</span>: <span style="color:#a6e22e">password</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">RoundTripper</span>: <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Transport</span>{
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">Proxy</span>:           <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">ProxyFromEnvironment</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">TLSClientConfig</span>: <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">tls</span>.<span style="color:#a6e22e">Config</span>{<span style="color:#a6e22e">InsecureSkipVerify</span>: <span style="color:#66d9ef">true</span>},
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// Set the username and password for basic authentication</span>
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// Note: this is not secure and should not be used in production</span>
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// Instead, use a secure authentication method such as OAuth2</span>
</span></span><span style="display:flex;"><span>				<span style="color:#75715e">// or a reverse proxy with authentication</span>
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">DialContext</span>: (<span style="color:#f92672">&amp;</span><span style="color:#a6e22e">net</span>.<span style="color:#a6e22e">Dialer</span>{
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">Timeout</span>:   <span style="color:#ae81ff">30</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>					<span style="color:#a6e22e">KeepAlive</span>: <span style="color:#ae81ff">30</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				}).<span style="color:#a6e22e">DialContext</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">ForceAttemptHTTP2</span>:     <span style="color:#66d9ef">true</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">MaxIdleConns</span>:          <span style="color:#ae81ff">100</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">IdleConnTimeout</span>:       <span style="color:#ae81ff">90</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">TLSHandshakeTimeout</span>:   <span style="color:#ae81ff">10</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">ExpectContinueTimeout</span>: <span style="color:#ae81ff">1</span> <span style="color:#f92672">*</span> <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span>,
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">ProxyConnectHeader</span>:    <span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Header</span>{},
</span></span><span style="display:flex;"><span>			},
</span></span><span style="display:flex;"><span>		},
</span></span><span style="display:flex;"><span>	})
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Create a new Prometheus API client</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">prometheusClient</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">v1</span>.<span style="color:#a6e22e">NewAPI</span>(<span style="color:#a6e22e">client</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Build the query string with the given label</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">query</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Sprintf</span>(<span style="color:#e6db74">`%s{%s=&#34;%s&#34;}`</span>, <span style="color:#a6e22e">my_metric</span>, <span style="color:#a6e22e">key</span>, <span style="color:#a6e22e">value</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Query Prometheus with the built query string</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">result</span>, <span style="color:#a6e22e">warnings</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">prometheusClient</span>.<span style="color:#a6e22e">Query</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Background</span>(), <span style="color:#a6e22e">query</span>, <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Now</span>())
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">nil</span>, <span style="color:#a6e22e">err</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">warnings</span>) &gt; <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">fmt</span>.<span style="color:#a6e22e">Println</span>(<span style="color:#e6db74">&#34;Warnings:&#34;</span>, <span style="color:#a6e22e">warnings</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#75715e">// Parse the query result into a slice of QueryResult structs</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> <span style="color:#a6e22e">queryResults</span> []<span style="color:#a6e22e">QueryResult</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">res</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">result</span>.(<span style="color:#a6e22e">model</span>.<span style="color:#a6e22e">Vector</span>) {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">queryResults</span> = append(<span style="color:#a6e22e">queryResults</span>, <span style="color:#a6e22e">QueryResult</span>{
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Metric</span>: <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">Metric</span>,
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">Value</span>:  <span style="color:#a6e22e">res</span>.<span style="color:#a6e22e">Value</span>,
</span></span><span style="display:flex;"><span>		})
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#a6e22e">queryResults</span>, <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>很好，感觉自己要失业了。</p>
        
        <hr><p>Published on 2023-04-27 at <a href='https://allens.tech/'>Allens' Blog</a>, last modified on 2023-04-27</p>]]></description><category>AI</category></item><item><title>学习笔记 - 并发编程 ☞ errgroup</title><link>https://allens.tech/post/202304262059/</link><pubDate>Wed, 26 Apr 2023 20:59:19 +0800</pubDate><author>allens.leng@gmail.com (Allens)</author><guid>https://allens.tech/post/202304262059/</guid><description>
<![CDATA[<h1>学习笔记 - 并发编程 ☞ errgroup</h1><p>Author: Allens(allens.leng@gmail.com)</p>
        
          <h2 id="描述">
<a class="header-anchor" href="#%e6%8f%8f%e8%bf%b0"></a>
描述
</h2><p>Go 的优势无非在于并发编程，当你需要对数组中每一个元素都组装一个信息的时候，就涉及到并发处理的问题，毕竟根据组装数据的复杂程度，处理时间会指数型上涨，下面通过 sync.WaitGroup 和 errgroup.Group 两中方式分别对这种情况进行了处理。</p>
<h3 id="syncwaitgroup-demo">
<a class="header-anchor" href="#syncwaitgroup-demo"></a>
sync.WaitGroup demo
</h3><div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#f92672">package</span> <span style="color:#a6e22e">main</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> (
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;context&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;encoding/json&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;sync&#34;</span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;testing&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#e6db74">&#34;github.com/stretchr/testify/assert&#34;</span>
</span></span><span style="display:flex;"><span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Class</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Id</span>      <span style="color:#66d9ef">int64</span>      <span style="color:#e6db74">`json:&#34;id&#34;`</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Name</span>    <span style="color:#66d9ef">string</span>     <span style="color:#e6db74">`json:&#34;name&#34;`</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Grade</span>   <span style="color:#66d9ef">string</span>     <span style="color:#e6db74">`json:&#34;grade&#34;`</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Student</span> []<span style="color:#f92672">*</span><span style="color:#a6e22e">Student</span> <span style="color:#e6db74">`json:&#34;student&#34;`</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">Student</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Id</span>      <span style="color:#66d9ef">int64</span>  <span style="color:#e6db74">`json:&#34;id&#34;`</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">ClassId</span> <span style="color:#66d9ef">int64</span>  <span style="color:#e6db74">`json:&#34;classId&#34;`</span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">Name</span>    <span style="color:#66d9ef">string</span> <span style="color:#e6db74">`json:&#34;name&#34;`</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">TestWaitGroup</span>(<span style="color:#a6e22e">t</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">testing</span>.<span style="color:#a6e22e">T</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> (
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">mu</span>       <span style="color:#a6e22e">sync</span>.<span style="color:#a6e22e">Mutex</span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">wg</span>       = <span style="color:#a6e22e">sync</span>.<span style="color:#a6e22e">WaitGroup</span>{}
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">errs</span>     = make([]<span style="color:#66d9ef">error</span>, <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">classArr</span> = []<span style="color:#f92672">*</span><span style="color:#a6e22e">Class</span>{{<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">1</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">2</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">3</span>}}
</span></span><span style="display:flex;"><span>	)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">wg</span>.<span style="color:#a6e22e">Add</span>(len(<span style="color:#a6e22e">classArr</span>))
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">item</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">classArr</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">go</span> <span style="color:#66d9ef">func</span>(<span style="color:#a6e22e">class</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">Class</span>) {
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">wg</span>.<span style="color:#a6e22e">Done</span>()
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">cancel</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">WithTimeout</span>(<span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Background</span>(), <span style="color:#a6e22e">time</span>.<span style="color:#a6e22e">Second</span><span style="color:#f92672">*</span><span style="color:#ae81ff">5</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">defer</span> <span style="color:#a6e22e">cancel</span>()
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">students</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">queryAllStudent</span>(<span style="color:#a6e22e">ctx</span>, <span style="color:#a6e22e">class</span>.<span style="color:#a6e22e">Id</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">mu</span>.<span style="color:#a6e22e">Lock</span>()
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">errs</span> = append(<span style="color:#a6e22e">errs</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>				<span style="color:#a6e22e">mu</span>.<span style="color:#a6e22e">Unlock</span>()
</span></span><span style="display:flex;"><span>				<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>			}
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">class</span>.<span style="color:#a6e22e">Student</span> = <span style="color:#a6e22e">students</span>
</span></span><span style="display:flex;"><span>		}(<span style="color:#a6e22e">item</span>)
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">wg</span>.<span style="color:#a6e22e">Wait</span>()
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">Equal</span>(<span style="color:#a6e22e">t</span>, len(<span style="color:#a6e22e">errs</span>), <span style="color:#ae81ff">0</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">bytes</span>, <span style="color:#a6e22e">err</span> <span style="color:#f92672">:=</span> <span style="color:#a6e22e">json</span>.<span style="color:#a6e22e">Marshal</span>(<span style="color:#a6e22e">classArr</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">assert</span>.<span style="color:#a6e22e">Nil</span>(<span style="color:#a6e22e">t</span>, <span style="color:#a6e22e">err</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">t</span>.<span style="color:#a6e22e">Log</span>(string(<span style="color:#a6e22e">bytes</span>))
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">queryAllStudent</span>(<span style="color:#a6e22e">ctx</span> <span style="color:#a6e22e">context</span>.<span style="color:#a6e22e">Context</span>, <span style="color:#a6e22e">classId</span> <span style="color:#66d9ef">int64</span>) ([]<span style="color:#f92672">*</span><span style="color:#a6e22e">Student</span>, <span style="color:#66d9ef">error</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">map</span>[<span style="color:#66d9ef">int64</span>][]<span style="color:#f92672">*</span><span style="color:#a6e22e">Student</span>{
</span></span><span style="display:flex;"><span>		<span style="color:#ae81ff">1</span>: []<span style="color:#f92672">*</span><span style="color:#a6e22e">Student</span>{{<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">1</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">2</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">3</span>}},
</span></span><span style="display:flex;"><span>		<span style="color:#ae81ff">2</span>: []<span style="color:#f92672">*</span><span style="color:#a6e22e">Student</span>{{<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">4</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">5</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">6</span>}},
</span></span><span style="display:flex;"><span>		<span style="color:#ae81ff">3</span>: []<span style="color:#f92672">*</span><span style="color:#a6e22e">Student</span>{{<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">7</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">8</span>}, {<span style="color:#a6e22e">Id</span>: <span style="color:#ae81ff">9</span>}},
</span></span><span style="display:flex;"><span>	}[<span style="color:#a6e22e">classId</span>], <span style="color:#66d9ef">nil</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>我之前都是这么写的，但是这样就会有一个问题，就是 err 的捕获比较难搞，要声明一个 errs ，且返回 err 的时候取 errs 的哪一个元素都感觉不是很合理。</p>
        
        <hr><p>Published on 2023-04-26 at <a href='https://allens.tech/'>Allens' Blog</a>, last modified on 2023-04-26</p>]]></description><category>学习笔记</category></item><item><title>学习笔记 - Gopher China</title><link>https://allens.tech/post/202012032000/</link><pubDate>Thu, 03 Dec 2020 20:00:00 +0800</pubDate><author>allens.leng@gmail.com (Allens)</author><guid>https://allens.tech/post/202012032000/</guid><description>
<![CDATA[<h1>学习笔记 - Gopher China</h1><p>Author: Allens(allens.leng@gmail.com)</p>
        
          <h2 id="描述">
<a class="header-anchor" href="#%e6%8f%8f%e8%bf%b0"></a>
描述
</h2><p>参加 Gopher China 2020 感觉所获颇丰，简单整理一下，共勉 …</p>
<h2 id="代码解耦">
<a class="header-anchor" href="#%e4%bb%a3%e7%a0%81%e8%a7%a3%e8%80%a6"></a>
代码解耦
</h2><ul>
<li>旧代码</li>
</ul>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-Go" data-lang="Go"><span style="display:flex;"><span><span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">FirstName</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">msg</span>.<span style="color:#a6e22e">Code</span> = <span style="color:#a6e22e">ErrFirstNameIsRequired</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">LastName</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">msg</span>.<span style="color:#a6e22e">Code</span> = <span style="color:#a6e22e">ErrLastNameIsRequired</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">Address</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">msg</span>.<span style="color:#a6e22e">Code</span> = <span style="color:#a6e22e">ErrAddressIsRequired</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">PostalCode</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">msg</span>.<span style="color:#a6e22e">Code</span> = <span style="color:#a6e22e">ErrPostalCodeIsRequired</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">req</span>.<span style="color:#a6e22e">City</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">msg</span>.<span style="color:#a6e22e">Code</span> = <span style="color:#a6e22e">ErrCityIsRequired</span>
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><ul>
<li>改动后</li>
</ul>
<blockquote>
<p>抽象一个方法</p>
</blockquote>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-Go" data-lang="Go"><span style="display:flex;"><span><span style="color:#75715e">// ValidateString 字符串验证结构</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">type</span> <span style="color:#a6e22e">ValidateString</span> <span style="color:#66d9ef">struct</span> {
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Str</span>  <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">Code</span> <span style="color:#66d9ef">int</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// ValidateEmptyString 验证字符串是否为空</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">ValidateEmptyString</span>(<span style="color:#a6e22e">s</span> []<span style="color:#f92672">*</span><span style="color:#a6e22e">ValidateString</span>) (<span style="color:#a6e22e">code</span> <span style="color:#66d9ef">int</span>, <span style="color:#a6e22e">empty</span> <span style="color:#66d9ef">bool</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> <span style="color:#a6e22e">_</span>, <span style="color:#a6e22e">v</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">range</span> <span style="color:#a6e22e">s</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">if</span> len(<span style="color:#a6e22e">v</span>.<span style="color:#a6e22e">Str</span>) <span style="color:#f92672">==</span> <span style="color:#ae81ff">0</span> {
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">empty</span> = <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">code</span> = <span style="color:#a6e22e">v</span>.<span style="color:#a6e22e">Code</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><blockquote>
<p>核心逻辑</p>
        
        <hr><p>Published on 2020-12-03 at <a href='https://allens.tech/'>Allens' Blog</a>, last modified on 2020-12-03</p>]]></description><category>学习笔记</category></item><item><title>学习笔记 - Go Request Header 中的 Host 为空</title><link>https://allens.tech/post/201911222100/</link><pubDate>Fri, 22 Nov 2019 21:00:00 +0800</pubDate><author>allens.leng@gmail.com (Allens)</author><guid>https://allens.tech/post/201911222100/</guid><description>
<![CDATA[<h1>学习笔记 - Go Request Header 中的 Host 为空</h1><p>Author: Allens(allens.leng@gmail.com)</p>
        
          <h2 id="描述">
<a class="header-anchor" href="#%e6%8f%8f%e8%bf%b0"></a>
描述
</h2><p>最近在写一个文件下载（下载一个 Shell 脚本并执行），遇到了获取 <code>Request Hostname</code> 为空的问题</p>
<h2 id="细节">
<a class="header-anchor" href="#%e7%bb%86%e8%8a%82"></a>
细节
</h2><p>模板：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/sh
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>set -e
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>curl -kSL https://XXX/download/linux_x<span style="color:#e6db74">`</span>getconf LONG_BIT<span style="color:#e6db74">`</span>/XXX_<span style="color:#e6db74">`</span>uname -m<span style="color:#e6db74">`</span> -o /usr/bin/XXX
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> <span style="color:#f92672">[</span> ! -s /usr/bin/XXX <span style="color:#f92672">]</span>; <span style="color:#66d9ef">then</span>
</span></span><span style="display:flex;"><span>    echo <span style="color:#e6db74">&#34;Download Error : No agent version suitable for the current system was found&#34;</span>;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">else</span>
</span></span><span style="display:flex;"><span>    chmod +x /usr/bin/XXX
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    XXX register --host  --paramA paramA --paramB paramB
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    XXX install
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    XXX start
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">fi</span>
</span></span></code></pre></div><p>代码：</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-go" data-lang="go"><span style="display:flex;"><span><span style="color:#66d9ef">func</span> <span style="color:#a6e22e">ShellDownload</span>(<span style="color:#a6e22e">c</span> <span style="color:#f92672">*</span><span style="color:#a6e22e">gin</span> <span style="color:#a6e22e">Context</span>) {
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">var</span> (
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">err</span>         <span style="color:#66d9ef">error</span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">paramA</span>      <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">paramB</span>      <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">content</span>     <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">hostname</span>    <span style="color:#66d9ef">string</span>
</span></span><span style="display:flex;"><span>	)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">defer</span> <span style="color:#66d9ef">func</span>() {
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>			<span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">String</span>(<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">StatusBadRequest</span>, <span style="color:#a6e22e">content</span>)
</span></span><span style="display:flex;"><span>			<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>		}
</span></span><span style="display:flex;"><span>	}()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">params</span> <span style="color:#f92672">:=</span> <span style="color:#66d9ef">map</span>[<span style="color:#66d9ef">string</span>]<span style="color:#66d9ef">interface</span>{}{
</span></span><span style="display:flex;"><span>		<span style="color:#e6db74">&#34;Host&#34;</span>:   <span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">Request</span>.<span style="color:#a6e22e">Header</span>.<span style="color:#a6e22e">Get</span>(<span style="color:#e6db74">&#34;Hostname&#34;</span>),
</span></span><span style="display:flex;"><span>		<span style="color:#e6db74">&#34;paramA&#34;</span>: <span style="color:#a6e22e">paramA</span>,
</span></span><span style="display:flex;"><span>		<span style="color:#e6db74">&#34;paramB&#34;</span>: <span style="color:#a6e22e">paramB</span>,
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">buf</span> <span style="color:#f92672">:=</span> <span style="color:#f92672">&amp;</span><span style="color:#a6e22e">bytes</span>.<span style="color:#a6e22e">Buffer</span>{}
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">err</span> = <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">Tpl</span>.<span style="color:#a6e22e">ExecuteTemplate</span>(<span style="color:#a6e22e">buf</span>, <span style="color:#a6e22e">config</span>.<span style="color:#a6e22e">InstallTpl</span>, <span style="color:#a6e22e">params</span>)
</span></span><span style="display:flex;"><span>	<span style="color:#66d9ef">if</span> <span style="color:#a6e22e">err</span> <span style="color:#f92672">!=</span> <span style="color:#66d9ef">nil</span> {
</span></span><span style="display:flex;"><span>		<span style="color:#a6e22e">content</span> = <span style="color:#e6db74">`echo &#34;Download Error : System Internal Error&#34;`</span>
</span></span><span style="display:flex;"><span>		<span style="color:#66d9ef">return</span>
</span></span><span style="display:flex;"><span>	}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	<span style="color:#a6e22e">c</span>.<span style="color:#a6e22e">String</span>(<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">Status0K</span>, <span style="color:#a6e22e">buf</span>.<span style="color:#a6e22e">String</span>())
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="总结">
<a class="header-anchor" href="#%e6%80%bb%e7%bb%93"></a>
总结
</h2><p>根据 <code>Go</code> 语言 <a href="https://pkg.go.dev/net/http">http</a> 包解释，当服务器接受的请求带有 <code>header line</code>，会把 <code>host</code> 的头从映射中删除，并把 <code>host</code> 放到 <code>Request.Host</code> 中，所以从 <code>Request.Host</code> 中获取就可以了，当然，如果你请求时指定 host 如果是直接放在 header 中也会被屏蔽掉。</p>
        
        <hr><p>Published on 2019-11-22 at <a href='https://allens.tech/'>Allens' Blog</a>, last modified on 2019-11-22</p>]]></description><category>学习笔记</category></item></channel></rss>