mirror of
https://github.com/teivah/100-go-mistakes.git
synced 2026-06-21 00:47:11 +08:00
Mistake 80, japanese
This commit is contained in:
parent
7ebb7b603f
commit
8b4a369846
7 changed files with 937 additions and 136 deletions
|
|
@ -1852,12 +1852,12 @@ The response contains both the error and success messages, and also the first HT
|
|||
|
||||
The mistake in this code is that `http.Error` does not stop the handler's execution, which means the success message and status code get written in addition to the error. Beyond an incorrect response, failing to return after writing an error can lead to the unwanted execution of code and unexpected side-effects. The following code adds the `return` statement following the `http.Error` and exhibits the desired behavior when ran:
|
||||
|
||||
```go hl_lines="5"
|
||||
```go
|
||||
func handler(w http.ResponseWriter, req *http.Request) {
|
||||
err := foo(req)
|
||||
if err != nil {
|
||||
http.Error(w, "foo", http.StatusInternalServerError)
|
||||
return
|
||||
return // Adds the return statement
|
||||
}
|
||||
|
||||
_, _ = w.Write([]byte("all good"))
|
||||
|
|
|
|||
|
|
@ -887,7 +887,7 @@ This repo is open to <a href="https://hacktoberfest.com/">Hacktoberfest</a>!
|
|||
</span><span id="__span-1-20"><a id="__codelineno-1-20" name="__codelineno-1-20" href="#__codelineno-1-20"></a><span class="kd">func</span><span class="w"> </span><span class="nx">printAlloc</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
|
||||
</span><span id="__span-1-21"><a id="__codelineno-1-21" name="__codelineno-1-21" href="#__codelineno-1-21"></a><span class="w"> </span><span class="kd">var</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="nx">runtime</span><span class="p">.</span><span class="nx">MemStats</span>
|
||||
</span><span id="__span-1-22"><a id="__codelineno-1-22" name="__codelineno-1-22" href="#__codelineno-1-22"></a><span class="w"> </span><span class="nx">runtime</span><span class="p">.</span><span class="nx">ReadMemStats</span><span class="p">(</span><span class="o">&</span><span class="nx">m</span><span class="p">)</span>
|
||||
</span><span id="__span-1-23"><a id="__codelineno-1-23" name="__codelineno-1-23" href="#__codelineno-1-23"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">"%d KB\n"</span><span class="p">,</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">Alloc</span><span class="o">/</span><span class="mi">1024</span><span class="p">)</span>
|
||||
</span><span id="__span-1-23"><a id="__codelineno-1-23" name="__codelineno-1-23" href="#__codelineno-1-23"></a><span class="w"> </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">"%d MB\n"</span><span class="p">,</span><span class="w"> </span><span class="nx">m</span><span class="p">.</span><span class="nx">Alloc</span><span class="o">/</span><span class="p">(</span><span class="mi">1024</span><span class="o">*</span><span class="mi">1024</span><span class="p">))</span>
|
||||
</span><span id="__span-1-24"><a id="__codelineno-1-24" name="__codelineno-1-24" href="#__codelineno-1-24"></a><span class="p">}</span>
|
||||
</span></code></pre></div>
|
||||
<p>We allocate an empty map, add 1 million elements, remove 1 million elements, and then run a GC. We also make sure to keep a reference to the map using <a href="https://pkg.go.dev/runtime#KeepAlive"><code>runtime.KeepAlive</code></a> so that the map isn’t collected as well. Let’s run this example:</p>
|
||||
|
|
@ -908,7 +908,7 @@ This repo is open to <a href="https://hacktoberfest.com/">Hacktoberfest</a>!
|
|||
</p>
|
||||
<figcaption>Figure 2: In case of a bucket overflow, Go allocates a new bucket and links the previous bucket to it.</figcaption>
|
||||
</figure>
|
||||
<p>Under the hood, a Go map is a pointer to a runtime.hmap struct. This struct contains multiple fields, including a B field, giving the number of buckets in the map:</p>
|
||||
<p>Under the hood, a Go map is a pointer to a <a href="https://github.com/golang/go/blob/0262ea1ff9ac3b9fd268a48fcaaa6811c20cbea2/src/runtime/map.go#L117-L131">runtime.hmap</a> struct. This struct contains multiple fields, including a B field, giving the number of buckets in the map:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="kd">type</span><span class="w"> </span><span class="nx">hmap</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span>
|
||||
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="w"> </span><span class="nx">B</span><span class="w"> </span><span class="kt">uint8</span><span class="w"> </span><span class="c1">// log_2 of # of buckets</span>
|
||||
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="w"> </span><span class="c1">// (can hold up to loadFactor * 2^B items)</span>
|
||||
|
|
|
|||
|
|
@ -3909,7 +3909,7 @@ the use case. However, we should see the two options as complementary. </p>
|
|||
<p class="admonition-title">Quote</p>
|
||||
<p>If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection.</p>
|
||||
</div>
|
||||
<p>Unlike a switch statement, where the first case with a match wins, the select state- ment selects randomly if multiple options are possible.</p>
|
||||
<p>Unlike a switch statement, where the first case with a match wins, the select statement selects randomly if multiple options are possible.</p>
|
||||
<p>This behavior might look odd at first, but there’s a good reason for it: to prevent possible starvation. Suppose the first possible communication chosen is based on the source order. In that case, we may fall into a situation where, for example, we only receive from one channel because of a fast sender. To prevent this, the language designers decided to use a random selection.</p>
|
||||
<p>When using <code>select</code> with multiple channels, we must remember that if multiple options are possible, the first case in the source order does not automatically win. Instead, Go selects randomly, so there’s no guarantee about which option will be chosen. To overcome this behavior, in the case of a single producer goroutine, we can use either unbuffered channels or a single channel.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/64-select-behavior/main.go">Source code <span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span></a></p>
|
||||
|
|
@ -4097,6 +4097,36 @@ the use case. However, we should see the two options as complementary. </p>
|
|||
<summary>TL;DR</summary>
|
||||
<p>To avoid unexpected behaviors in HTTP handler implementations, make sure you don’t miss the <code>return</code> statement if you want a handler to stop after <code>http.Error</code>.</p>
|
||||
</details>
|
||||
<p>Consider the following HTTP handler that handles an error from <code>foo</code> using <code>http.Error</code>:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-48-1"><a id="__codelineno-48-1" name="__codelineno-48-1" href="#__codelineno-48-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">handler</span><span class="p">(</span><span class="nx">w</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span><span class="w"> </span><span class="nx">req</span><span class="w"> </span><span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
</span><span id="__span-48-2"><a id="__codelineno-48-2" name="__codelineno-48-2" href="#__codelineno-48-2"></a><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">foo</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
|
||||
</span><span id="__span-48-3"><a id="__codelineno-48-3" name="__codelineno-48-3" href="#__codelineno-48-3"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
|
||||
</span><span id="__span-48-4"><a id="__codelineno-48-4" name="__codelineno-48-4" href="#__codelineno-48-4"></a><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">Error</span><span class="p">(</span><span class="nx">w</span><span class="p">,</span><span class="w"> </span><span class="s">"foo"</span><span class="p">,</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">)</span>
|
||||
</span><span id="__span-48-5"><a id="__codelineno-48-5" name="__codelineno-48-5" href="#__codelineno-48-5"></a><span class="w"> </span><span class="p">}</span>
|
||||
</span><span id="__span-48-6"><a id="__codelineno-48-6" name="__codelineno-48-6" href="#__codelineno-48-6"></a>
|
||||
</span><span id="__span-48-7"><a id="__codelineno-48-7" name="__codelineno-48-7" href="#__codelineno-48-7"></a><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">Write</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="s">"all good"</span><span class="p">))</span>
|
||||
</span><span id="__span-48-8"><a id="__codelineno-48-8" name="__codelineno-48-8" href="#__codelineno-48-8"></a><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">WriteHeader</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusCreated</span><span class="p">)</span>
|
||||
</span><span id="__span-48-9"><a id="__codelineno-48-9" name="__codelineno-48-9" href="#__codelineno-48-9"></a><span class="p">}</span>
|
||||
</span></code></pre></div>
|
||||
<p>If we run this code and <code>err != nil</code>, the HTTP response would be:</p>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-49-1"><a id="__codelineno-49-1" name="__codelineno-49-1" href="#__codelineno-49-1"></a>foo
|
||||
</span><span id="__span-49-2"><a id="__codelineno-49-2" name="__codelineno-49-2" href="#__codelineno-49-2"></a>all good
|
||||
</span></code></pre></div>
|
||||
<p>The response contains both the error and success messages, and also the first HTTP status code, 500. There would also be a warning log indicating that we attempted to write the status code multiple times:</p>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-50-1"><a id="__codelineno-50-1" name="__codelineno-50-1" href="#__codelineno-50-1"></a>2023/10/10 16:45:33 http: superfluous response.WriteHeader call from main.handler (main.go:20)
|
||||
</span></code></pre></div>
|
||||
<p>The mistake in this code is that <code>http.Error</code> does not stop the handler's execution, which means the success message and status code get written in addition to the error. Beyond an incorrect response, failing to return after writing an error can lead to the unwanted execution of code and unexpected side-effects. The following code adds the <code>return</code> statement following the <code>http.Error</code> and exhibits the desired behavior when ran:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-51-1"><a id="__codelineno-51-1" name="__codelineno-51-1" href="#__codelineno-51-1"></a><span class="kd">func</span><span class="w"> </span><span class="nx">handler</span><span class="p">(</span><span class="nx">w</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span><span class="w"> </span><span class="nx">req</span><span class="w"> </span><span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
</span><span id="__span-51-2"><a id="__codelineno-51-2" name="__codelineno-51-2" href="#__codelineno-51-2"></a><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">foo</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
|
||||
</span><span id="__span-51-3"><a id="__codelineno-51-3" name="__codelineno-51-3" href="#__codelineno-51-3"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span>
|
||||
</span><span id="__span-51-4"><a id="__codelineno-51-4" name="__codelineno-51-4" href="#__codelineno-51-4"></a><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">Error</span><span class="p">(</span><span class="nx">w</span><span class="p">,</span><span class="w"> </span><span class="s">"foo"</span><span class="p">,</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">)</span>
|
||||
</span><span id="__span-51-5"><a id="__codelineno-51-5" name="__codelineno-51-5" href="#__codelineno-51-5"></a><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="c1">// Adds the return statement</span>
|
||||
</span><span id="__span-51-6"><a id="__codelineno-51-6" name="__codelineno-51-6" href="#__codelineno-51-6"></a><span class="w"> </span><span class="p">}</span>
|
||||
</span><span id="__span-51-7"><a id="__codelineno-51-7" name="__codelineno-51-7" href="#__codelineno-51-7"></a>
|
||||
</span><span id="__span-51-8"><a id="__codelineno-51-8" name="__codelineno-51-8" href="#__codelineno-51-8"></a><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">Write</span><span class="p">([]</span><span class="nb">byte</span><span class="p">(</span><span class="s">"all good"</span><span class="p">))</span>
|
||||
</span><span id="__span-51-9"><a id="__codelineno-51-9" name="__codelineno-51-9" href="#__codelineno-51-9"></a><span class="w"> </span><span class="nx">w</span><span class="p">.</span><span class="nx">WriteHeader</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusCreated</span><span class="p">)</span>
|
||||
</span><span id="__span-51-10"><a id="__codelineno-51-10" name="__codelineno-51-10" href="#__codelineno-51-10"></a><span class="p">}</span>
|
||||
</span></code></pre></div>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/80-http-return/main.go">Source code <span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></span></a></p>
|
||||
<h3 id="using-the-default-http-client-and-server-81">Using the default HTTP client and server (#81)</h3>
|
||||
<details class="info" open="open">
|
||||
|
|
@ -4155,7 +4185,7 @@ the use case. However, we should see the two options as complementary. </p>
|
|||
<ul>
|
||||
<li>Use time methods to preserve the accuracy of a benchmark.</li>
|
||||
<li>Increasing benchtime or using tools such as benchstat can be helpful when dealing with micro-benchmarks.</li>
|
||||
<li>Be careful with the results of a micro-benchmark if the system that ends up running the application is different from the one running the micro-bench- mark.</li>
|
||||
<li>Be careful with the results of a micro-benchmark if the system that ends up running the application is different from the one running the micro-benchmark.</li>
|
||||
<li>Make sure the function under test leads to a side effect, to prevent compiler optimizations from fooling you about the benchmark results.</li>
|
||||
<li>To prevent the observer effect, force a benchmark to re-create the data used by a CPU-bound function.</li>
|
||||
</ul>
|
||||
|
|
|
|||
1003
site/ja/index.html
1003
site/ja/index.html
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -2,67 +2,67 @@
|
|||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://100go.co/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/20-slice/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/28-maps-memory-leaks/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/56-concurrency-faster/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/89-benchmarks/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/9-generics/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/98-profiling-execution-tracing/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/book/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/chapter-1/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/external/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/ja/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/jobs/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/zh/</loc>
|
||||
<lastmod>2023-10-14</lastmod>
|
||||
<lastmod>2023-11-28</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
</urlset>
|
||||
Binary file not shown.
Loading…
Reference in a new issue