mirror of
https://github.com/teivah/100-go-mistakes.git
synced 2026-06-23 18:06:53 +08:00
Add tl;dr
This commit is contained in:
parent
aa06a2f79d
commit
55dcbb6464
1 changed files with 15 additions and 20 deletions
35
README.md
35
README.md
|
|
@ -166,9 +166,6 @@ The value element in a `range` loop is a copy. Therefore, to mutate a struct, fo
|
||||||
|
|
||||||
#### #31: Ignoring how arguments are evaluated in `range` loops (channels and arrays)
|
#### #31: Ignoring how arguments are evaluated in `range` loops (channels and arrays)
|
||||||
|
|
||||||
* Channels
|
|
||||||
* Arrays
|
|
||||||
|
|
||||||
Understanding that the expression passed to the `range` operator is evaluated only once before the beginning of the loop can help you avoid common mistakes such as inefficient assignment in channel or slice iteration.
|
Understanding that the expression passed to the `range` operator is evaluated only once before the beginning of the loop can help you avoid common mistakes such as inefficient assignment in channel or slice iteration.
|
||||||
|
|
||||||
#### #32: Ignoring the impacts of using pointer elements in `range` loops
|
#### #32: Ignoring the impacts of using pointer elements in `range` loops
|
||||||
|
|
@ -177,7 +174,7 @@ Using a local variable or accessing an element using an index, you can prevent m
|
||||||
|
|
||||||
#### #33: Making wrong assumptions during map iterations (ordering and map insert during iteration)
|
#### #33: Making wrong assumptions during map iterations (ordering and map insert during iteration)
|
||||||
|
|
||||||
To ensure predictable outputs when using maps, remember that a map data structure
|
To ensure predictable outputs when using maps, remember that a map data structure:
|
||||||
* Doesn’t order the data by keys
|
* Doesn’t order the data by keys
|
||||||
* Doesn’t preserve the insertion order
|
* Doesn’t preserve the insertion order
|
||||||
* Doesn’t have a deterministic iteration order
|
* Doesn’t have a deterministic iteration order
|
||||||
|
|
@ -247,7 +244,7 @@ Passing a pointer to a `defer` function and wrapping a call inside a closure are
|
||||||
|
|
||||||
#### #48: Panicking
|
#### #48: Panicking
|
||||||
|
|
||||||
* Using `panic` is an option to deal with errors in Go. However, it should only be used sparingly in unrecoverable conditions: for example, to signal a programmer error or when you fail to load a mandatory dependency.
|
Using `panic` is an option to deal with errors in Go. However, it should only be used sparingly in unrecoverable conditions: for example, to signal a programmer error or when you fail to load a mandatory dependency.
|
||||||
|
|
||||||
#### #49: Ignoring when to wrap an error
|
#### #49: Ignoring when to wrap an error
|
||||||
|
|
||||||
|
|
@ -458,61 +455,59 @@ The `iotest` package helps write io.Reader and test that an application is toler
|
||||||
#### #89: Writing inaccurate benchmarks
|
#### #89: Writing inaccurate benchmarks
|
||||||
* Not resetting or pausing the timer
|
* Not resetting or pausing the timer
|
||||||
|
|
||||||
Use time methods to preserve the accuracy of a benchmark.
|
Use time methods to preserve the accuracy of a benchmark.
|
||||||
|
|
||||||
* Making wrong assumptions about micro-benchmarks
|
* Making wrong assumptions about micro-benchmarks
|
||||||
|
|
||||||
Increasing `benchtime` or using tools such as `benchstat` can be helpful when dealing with micro-benchmarks.
|
Increasing `benchtime` or using tools such as `benchstat` can be helpful when dealing with micro-benchmarks.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
* Not being careful about compiler optimizations
|
* Not being careful about compiler optimizations
|
||||||
|
|
||||||
Make sure the function under test leads to a side effect, to prevent compiler optimizations from fooling you about the benchmark results.
|
Make sure the function under test leads to a side effect, to prevent compiler optimizations from fooling you about the benchmark results.
|
||||||
|
|
||||||
* Being fooled by the observer effect
|
* Being fooled by the observer effect
|
||||||
|
|
||||||
To prevent the observer effect, force a benchmark to re-create the data used by a CPU-bound function.
|
To prevent the observer effect, force a benchmark to re-create the data used by a CPU-bound function.
|
||||||
|
|
||||||
#### #90: Not exploring all the Go testing features
|
#### #90: Not exploring all the Go testing features
|
||||||
* Code coverage
|
* Code coverage
|
||||||
|
|
||||||
Use code coverage with the `-coverprofile` flag to quickly see which part of the code needs more attention.
|
Use code coverage with the `-coverprofile` flag to quickly see which part of the code needs more attention.
|
||||||
|
|
||||||
* Testing from a different package
|
* Testing from a different package
|
||||||
|
|
||||||
Place unit tests in a different package to enforce writing tests that focus on an exposed behavior, not internals.
|
Place unit tests in a different package to enforce writing tests that focus on an exposed behavior, not internals.
|
||||||
|
|
||||||
* Utility functions
|
* Utility functions
|
||||||
|
|
||||||
Handling errors using the `*testing.T` variable instead of the classic `if err != nil` makes code shorter and easier to read.
|
Handling errors using the `*testing.T` variable instead of the classic `if err != nil` makes code shorter and easier to read.
|
||||||
|
|
||||||
* Setup and teardown
|
* Setup and teardown
|
||||||
|
|
||||||
You can use setup and teardown functions to configure a complex environment, such as in the case of integration tests.
|
You can use setup and teardown functions to configure a complex environment, such as in the case of integration tests.
|
||||||
|
|
||||||
### Chapter 12 - Optimizations
|
### Chapter 12 - Optimizations
|
||||||
|
|
||||||
#### #91: Not understanding CPU caches
|
#### #91: Not understanding CPU caches
|
||||||
* CPU architecture
|
* CPU architecture
|
||||||
|
|
||||||
Understanding how to use CPU caches is important for optimizing CPU-bound applications because the L1 cache is about 50 to 100 times faster than the main memory.
|
Understanding how to use CPU caches is important for optimizing CPU-bound applications because the L1 cache is about 50 to 100 times faster than the main memory.
|
||||||
|
|
||||||
* Cache line
|
* Cache line
|
||||||
|
|
||||||
Being conscious of the cache line concept is critical to understanding how to organize data in data-intensive applications. A CPU doesn’t fetch memory word by word; instead, it usually copies a memory block to a 64-byte cache line. To get the most out of each individual cache line, enforce spatial locality.
|
Being conscious of the cache line concept is critical to understanding how to organize data in data-intensive applications. A CPU doesn’t fetch memory word by word; instead, it usually copies a memory block to a 64-byte cache line. To get the most out of each individual cache line, enforce spatial locality.
|
||||||
|
|
||||||
* Slice of structs vs. struct of slices
|
* Slice of structs vs. struct of slices
|
||||||
|
|
||||||
See above.
|
|
||||||
|
|
||||||
* Predictability
|
* Predictability
|
||||||
|
|
||||||
Making code predictable for the CPU can also be an efficient way to optimize certain functions. For example, a unit or constant stride is predictable for the CPU, but a non-unit stride (for example, a linked list) isn’t predictable.
|
Making code predictable for the CPU can also be an efficient way to optimize certain functions. For example, a unit or constant stride is predictable for the CPU, but a non-unit stride (for example, a linked list) isn’t predictable.
|
||||||
|
|
||||||
* Cache placement policy
|
* Cache placement policy
|
||||||
|
|
||||||
To avoid a critical stride, hence utilizing only a tiny portion of the cache, be aware that caches are partitioned.
|
To avoid a critical stride, hence utilizing only a tiny portion of the cache, be aware that caches are partitioned.
|
||||||
|
|
||||||
#### #92: Writing concurrent code that leads to false sharing
|
#### #92: Writing concurrent code that leads to false sharing
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue