<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Indexing on cublr's blueprint</title><link>https://b.cublr.com/tags/indexing/</link><description>Recent content in Indexing on cublr's blueprint</description><language>en</language><managingEditor>sparkstar@empas.com (sparkstar)</managingEditor><webMaster>sparkstar@empas.com (sparkstar)</webMaster><lastBuildDate>Sun, 27 Mar 2022 20:00:00 +0900</lastBuildDate><atom:link href="https://b.cublr.com/tags/indexing/index.xml" rel="self" type="application/rss+xml"/><item><title>Go에서의 빠른 Hex decode</title><link>https://b.cublr.com/posts/go%EC%97%90%EC%84%9C%EC%9D%98-%EB%B9%A0%EB%A5%B8-hex-decode/</link><pubDate>Sun, 27 Mar 2022 20:00:00 +0900</pubDate><author>sparkstar@empas.com (sparkstar)</author><guid>https://b.cublr.com/posts/go%EC%97%90%EC%84%9C%EC%9D%98-%EB%B9%A0%EB%A5%B8-hex-decode/</guid><description>&lt;p&gt;인코딩은 어떤 데이터를 원하는 포맷으로 변경시키는 것을 말한다. 만약 &lt;code&gt;string&lt;/code&gt;을 &lt;code&gt;base64&lt;/code&gt;로 변경시켜야 하는 경우 string을 b64로 인코딩한다고 한다. 반대 방향의 변환은 디코딩이라고 부른다. 정확히는 방향이 반대일 때 디코딩은 아니고, 주체가 어떤 것이냐에 따라 다르다고 할 수 있다. 예를 들어 b64를 디코딩하여 문자열을 만들 수 있고, 또 b64를 문자열로 인코딩할 수도 있을 것이다. 두 연산의 결과는 같겠지만.&lt;/p&gt;
&lt;p&gt;아무튼 go에서는 &lt;a href="https://pkg.go.dev/encoding/hex"&gt;encoding/hex&lt;/a&gt;패키지에서는 다음과 같은 함수를 제공한다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;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;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Encode&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; &lt;span style="color:#75715e"&gt;// Hello Gopher! -&amp;gt; 48656c6c6f20476f7068657221&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Decode&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt; &lt;span style="color:#75715e"&gt;// 48656c6c6f20476f7068657221 -&amp;gt; Hello Gopher!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Encode&lt;/code&gt;를 사용하여 문자열을 &lt;code&gt;hex string&lt;/code&gt;으로 변경한다. 반대로 Decode를 사용하여 hex string을 다시 &lt;code&gt;문자열&lt;/code&gt;로 변경한다.&lt;/p&gt;
&lt;h3 id="encode"&gt;Encode&lt;/h3&gt;
&lt;p&gt;hex string은 문자열이지만 가능한 문자가 한정적이다. 16진수는 0~F까지 표현하기 때문이다. 16문자를 가지고 문자열을 만들어낸다. 그래서 함수 Encode에서는 파라미터 &lt;code&gt;src&lt;/code&gt;를 사용하여 다음과 같은 &lt;code&gt;dst&lt;/code&gt;를 만들어낼 수 있다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;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;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;hextable&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;0123456789abcdef&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Encode&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) &lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;v&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;] = &lt;span style="color:#a6e22e"&gt;hextable&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;+&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;] = &lt;span style="color:#a6e22e"&gt;hextable&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;v&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0x0f&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;) &lt;span style="color:#f92672"&gt;*&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/encoding/hex/hex.go;l=25&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;바이트는 0x00~0xFF의 범위를 가지므로 위와 같이 변형하면 된다. &lt;code&gt;src&lt;/code&gt;의 크기만큼 루프를 돌면서 다음의 작업을 수행한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dst[j] = hextable[v&amp;gt;&amp;gt;4]&lt;/code&gt;: &lt;code&gt;&amp;gt;&amp;gt;4&lt;/code&gt;는 바이트 하나를 오른쪽 4번 시프트하는데 이렇게 하면 leftmost 비트 4개를 얻을 수 있다. 이 값을 인덱스로 해서 &lt;code&gt;hextable&lt;/code&gt;에 있는 값을 가져온다. 예를 들어 v가 &lt;code&gt;00101111&lt;/code&gt;이었다면 시프트해서 &lt;code&gt;00000010&lt;/code&gt;이 되고, 이는 2라서 hextable[2]가 된다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dst[j+1] = hextable[v&amp;amp;0x0f]&lt;/code&gt;: rightmost 비트를 가져온다. 비트 오른쪽 4개를 얻기 위해서 &lt;code&gt;&amp;amp;&lt;/code&gt;를 하였다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;이렇게 돌면서 비트로 인덱스를 찾아 dst를 한 글자씩 채워나가면 바로 Encode가 된다.&lt;/p&gt;
&lt;h3 id="decode"&gt;Decode&lt;/h3&gt;
&lt;p&gt;Decode는 hex string 두 글자를 보고 이를 다시 바이트로 역변환하면 된다. 들어올 수 있는 가능한 문자는 0부터 9, a부터 f까지라서, 숫자와 문자를 각각 그룹이라고 생각하면 해당 그룹에 포함된 문자를 그 그룹의 처음 문자로 아스키코드 뺄셈을 한다. 그러면 결과는 그 그룹의 순서가 리턴된다. 만약 그룹이 문자였다면 +10을 해야 16진수 a가 된다.&lt;/p&gt;
&lt;p&gt;그 코드는 아래와 같다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;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;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Decode&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; ; &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &amp;lt; len(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fromHexChar&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; !&lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;InvalidByteError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fromHexChar&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; !&lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;InvalidByteError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;] = (&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) | &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;)&lt;span style="color:#f92672"&gt;%&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Check for invalid char before reporting bad length,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// since the invalid char (if present) is an earlier problem.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;_&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fromHexChar&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]); !&lt;span style="color:#a6e22e"&gt;ok&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;InvalidByteError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ErrLength&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// fromHexChar converts a hex character into its value and a success flag.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fromHexChar&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) (&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;bool&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;switch&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;9&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;0&amp;#39;&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;f&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;a&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;case&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;=&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;F&amp;#39;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;c&lt;/span&gt; &lt;span style="color:#f92672"&gt;-&lt;/span&gt; &lt;span style="color:#e6db74"&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;10&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// https://cs.opensource.google/go/go/+/refs/tags/go1.18:src/encoding/hex/hex.go;l=84&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Decode&lt;/code&gt;에서는 루프를 돌며 값을 처리한다. Encode와 비슷하므로 크게 설명할 것은 없다. &lt;code&gt;fromHexChar&lt;/code&gt;를 통해 switch-case에서 hex string의 그룹을 찾는다. &lt;code&gt;a&lt;/code&gt; 와 &lt;code&gt;A&lt;/code&gt;는 같은 hex이므로 부득이하게 그룹을 나눈다. case의 조건은 &lt;a href="https://en.wikipedia.org/wiki/Yoda_conditions"&gt;yoda condition&lt;/a&gt;으로 작성되었다.&lt;/p&gt;
&lt;h3 id="변경된-decode"&gt;변경된 Decode&lt;/h3&gt;
&lt;p&gt;사실 이 글을 쓰게 된 이유는 최근 go 리파지터리에 올라온 다음과 같은 &lt;a href="https://github.com/golang/go/pull/51432"&gt;커밋&lt;/a&gt;을 보았기 때문이다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;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;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;reverseHexTable&lt;/span&gt; = &lt;span style="color:#e6db74"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\x0a\x0b\x0c\x0d\x0e\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt; &lt;span style="color:#f92672"&gt;+&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Decode&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt; []&lt;span style="color:#66d9ef"&gt;byte&lt;/span&gt;) (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;error&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;0&lt;/span&gt;, &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; ; &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &amp;lt; len(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;); &lt;span style="color:#a6e22e"&gt;j&lt;/span&gt; &lt;span style="color:#f92672"&gt;+=&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;p&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;q&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reverseHexTable&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reverseHexTable&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;q&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &amp;gt; &lt;span style="color:#ae81ff"&gt;0x0f&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;InvalidByteError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;p&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &amp;gt; &lt;span style="color:#ae81ff"&gt;0x0f&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;InvalidByteError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;q&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;dst&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;] = (&lt;span style="color:#a6e22e"&gt;a&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;4&lt;/span&gt;) | &lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;&lt;span style="color:#f92672"&gt;++&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; len(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;)&lt;span style="color:#f92672"&gt;%&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;2&lt;/span&gt; &lt;span style="color:#f92672"&gt;==&lt;/span&gt; &lt;span style="color:#ae81ff"&gt;1&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Check for invalid char before reporting bad length,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// since the invalid char (if present) is an earlier problem.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;reverseHexTable&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;]] &amp;gt; &lt;span style="color:#ae81ff"&gt;0x0f&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;InvalidByteError&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;src&lt;/span&gt;[&lt;span style="color:#a6e22e"&gt;j&lt;/span&gt;&lt;span style="color:#f92672"&gt;-&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;1&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;ErrLength&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;i&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// https://github.com/golang/go/pull/51432/files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Encode&lt;/code&gt;에서 &lt;code&gt;hexTable&lt;/code&gt;을 참조하는 것처럼, &lt;code&gt;Decode&lt;/code&gt;에서는 &lt;code&gt;reverseHexTable&lt;/code&gt;을 참조하도록 변경했다. &lt;code&gt;switch-case&lt;/code&gt;에서 조건별로 분기하지 않고, 그 값을 그대로 테이블에서 찾아 사용하도록 한 것이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;reverseHextable&lt;/code&gt;은 아스키 코드에서 hex에 대응하는 값만을 실제 바이트로 매핑했다. 따라서 &lt;code&gt;fromHexChar&lt;/code&gt;에서 세 그룹으로 나누었던 부분만 바이트로 매핑하고 나머지는 전부 &lt;code&gt;\xff&lt;/code&gt;로 채워 두었다. 그래서 이 테이블을 참조하는 루프에서는 &lt;code&gt;0x0f&lt;/code&gt;보다 큰 값이 디코딩 대상인 경우 &lt;code&gt;InvalidByteError()&lt;/code&gt;를 리턴하도록 처리되었다.&lt;/p&gt;
&lt;p&gt;이렇게 하여 기존 코드 대비해서 함수 하나가 삭제되고 대신에 256바이트짜리 테이블이 추가된다. 속도는 해당 유저가 올린 내용을 보면 벤치마크를 해 두어서 여기에 한번 옮겨본다.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;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;"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Implement hex decode using a 256 byte lookup table instead of branching logic.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;In happy flow, uses 3x 64 byte (or 5x 32 byte) cache lines.
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;name old time/op new time/op delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/256-64 223ns ± 3% 135ns ± 2% -39.64% (p=0.000 n=8+8)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/1024-64 872ns ± 2% 512ns ± 2% -41.25% (p=0.000 n=8+8)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/4096-64 3.43µs ± 1% 2.01µs ± 2% -41.31% (p=0.001 n=7+7)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/16384-64 13.9µs ± 1% 8.0µs ± 1% -42.69% (p=0.000 n=8+7)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;name old speed new speed delta
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/256-64 1.15GB/s ± 3% 1.90GB/s ± 2% +65.66% (p=0.000 n=8+8)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/1024-64 1.17GB/s ± 2% 2.00GB/s ± 2% +70.22% (p=0.000 n=8+8)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/4096-64 1.20GB/s ± 1% 2.04GB/s ± 2% +70.39% (p=0.001 n=7+7)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Decode/16384-64 1.18GB/s ± 1% 2.06GB/s ± 1% +74.49% (p=0.000 n=8+7)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;코드를 작성한 사람의 코멘트로는 다음과 같은 장점이 있다고 되어 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Also reduces amd64 object size by 766 bytes, despite the extra RODATA due to removal of &lt;code&gt;fromHexChar()&lt;/code&gt; and duplicated inlined versions of it and simplification of &lt;code&gt;Decode()&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="왜-map이-아닌가"&gt;왜 map이 아닌가?&lt;/h3&gt;
&lt;p&gt;그런데 잘 생각해보면 256바이트의 추가 테이블을 쓰지 않고, 맵으로 키와 매핑하면 더 효율적이 아닌가? 하는 생각이 들 수 있다. 왜냐하면 결국 reverseHexTable이 하는 일은 어떤 인덱스로 해당 값을 찾을 수 있게 하는 것이 목적이고, 그렇다면 똑같은 인덱싱 연산을 하는 &lt;code&gt;map&lt;/code&gt;을 쓰는 것이 더 낫지 않을까? 하는 것이다. 만약 맵으로 한다면 ASCII에 대응하는 키 16개만 가지고 있으면 똑같이 값을 변환할 수 있으니까 공간적으로도 더 효율적일 수 있다. 단순 따져서 맵에 우리가 모르는 추가 구현이 있어서 실 사용량은 16바이트+@라 하더라도 설마 256바이트보다 클까? 하는 것이다.&lt;/p&gt;
&lt;p&gt;그러나 아쉽게도 그렇지는 않다. 간단하게 이야기하면 맵 억세스 최적화는 컴파일 타임에 이루어지지 않는다. 반면 &lt;code&gt;switch&lt;/code&gt;는 &lt;code&gt;case&lt;/code&gt;에 둔 식이 상수라면 컴파일 타임에 최적화시키는 것이 가능하다. 그래서 인터넷에서 흔히 검색할 수 있는 switch-case vs. map의 경우는 거의 모든 케이스에서 switch-case가 항상 빠르다.&lt;/p&gt;
&lt;p&gt;&lt;img src="images/Hash_Table.png" alt="Hash Table" title="Hash table, https://en.wikipedia.org/wiki/Hash_table"&gt;&lt;/p&gt;
&lt;p&gt;slice, 슬라이스 또한 맵처럼 인덱싱할 수 있다. 인덱스를 주고 해당 값에 억세스할 수 있다. 차이점이 있다면 슬라이스는 연속된 메모리가 늘어져 있는 형태이므로 단순 연산으로도 해당 위치의 값을 찾을 수 있다. 반면 맵은 다르다. go의 맵은 &lt;code&gt;hashmap&lt;/code&gt;형태로 구현되어 있는데, &lt;a href="https://en.wikipedia.org/wiki/Hash_table"&gt;해시 테이블&lt;/a&gt;을 통해 키로서 값을 찾는다. 즉 키로 값을 찾는 것에 슬라이스보다 추가적인 연산이 필요하다는 뜻이다. 해시 테이블이라 하면 아무래도 효율적이고 대부분 빠르긴 하겠지만 대부분의 연산에 충돌 케이스를 핸들링하거나, 탐색을 할 때 링크드 리스트를 탐색하거나 하는 케이스가 발생하므로 간단한 덧셈을 통해 값에 접근할 수 있는 슬라이스보다 느릴 수 밖에 없겠다. 멀리서 보면 큰 차이는 없겠지만.&lt;/p&gt;
&lt;h3 id="결론"&gt;결론&lt;/h3&gt;
&lt;p&gt;나름대로 결론을 내리면 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;if-else&lt;/code&gt;가 좋아요 &lt;code&gt;switch-case&lt;/code&gt;가 좋아요?: 그냥 아무거나 써도 컴파일되면 똑같다. 조건절이 &lt;code&gt;constant&lt;/code&gt;인 것이 효율적이다.&lt;/li&gt;
&lt;li&gt;조건절이 너무 많으면 어떻게 될까요?: 이진 탐색으로 최적화되니까 그냥 적당히 써도 된다.&lt;/li&gt;
&lt;li&gt;go의 map은 &lt;code&gt;hashmap&lt;/code&gt;으로 구현되어 있음&lt;/li&gt;
&lt;li&gt;&lt;code&gt;map&lt;/code&gt;도 &lt;code&gt;O(1)&lt;/code&gt;이니까 빠를 것 같아요: 일반적인 상황에서는 제일 빠르고 무난하다. 몸 비틀면서 최적화한다면 이런저런 방법을 찾을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="읽어보면-괜찮은--참고-사항들"&gt;읽어보면 괜찮은 참고 사항들&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.slideshare.net/david74chou/how-the-go-runtime-implement-maps-efficiently"&gt;How the Go runtime implement maps efficiently&lt;/a&gt;: 다른 언어의 map과 비교해서 어떻게 다른지, Go에서는 어떻게 동작하는지 심플한 설명이 작성되어 있음&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boltandnuts.wordpress.com/2017/11/20/go-slice-vs-maps/"&gt;Go Slice vs. Map&lt;/a&gt;: direct lookup의 경우 slice가 압도적으로 빠르다 - 위 pull request의 케이스&lt;/li&gt;
&lt;li&gt;&lt;a href="https://groups.google.com/g/golang-nuts/c/IURR4Z2SY7M/m/R7ORD_yDix4J"&gt;switch-case implementaed is as follows&amp;hellip;&lt;/a&gt;: if-else, switch, 상수 파라미터&amp;hellip; 관련. 스위치만 이야기하면, 3개 이상의 상수 case일 때는 이진 탐색한다.(groups of larger than 3 constant cases are binary divided and conquered.)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/46789259/map-vs-switch-performance-in-go"&gt;map vs switch performance in go&lt;/a&gt;: branch 가능한 방법 중 Map/Slice/Switch 세 개의 퍼포먼스가 대략적으로 어떤지 답변에 달려 있다.&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>