mirror of
https://github.com/teivah/100-go-mistakes.git
synced 2026-06-21 00:47:11 +08:00
Home page
This commit is contained in:
parent
9d79a008d0
commit
027773e80f
6 changed files with 206 additions and 199 deletions
194
docs/index.md
194
docs/index.md
|
|
@ -8,10 +8,6 @@ If you want to engage with the community (asking questions, discussing options,
|
|||
|
||||
You're currently viewing a new version that I'm enriching with significantly more content. Yet, this version is still under development; please be gentle if you find an issue, and feel free to create a PR.
|
||||
|
||||
<!-- TODO Include full excerpts -->
|
||||
|
||||
<!-- TODO Include chapter-1.md -->
|
||||
|
||||

|
||||
|
||||
## Code and Project Organization
|
||||
|
|
@ -24,7 +20,7 @@ If you want to engage with the community (asking questions, discussing options,
|
|||
|
||||
Variable shadowing occurs when a variable name is redeclared in an inner block, but this practice is prone to mistakes. Imposing a rule to forbid shadowed variables depends on personal taste. For example, sometimes it can be convenient to reuse an existing variable name like `err` for errors. Yet, in general, we should remain cautious because we now know that we can face a scenario where the code compiles, but the variable that receives the value is not the one expected.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/1-variable-shadowing/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/1-variable-shadowing/main.go)
|
||||
|
||||
### Unnecessary nested code (#2)
|
||||
|
||||
|
|
@ -77,7 +73,7 @@ if s == "" {
|
|||
|
||||
Writing readable code is an important challenge for every developer. Striving to reduce the number of nested blocks, aligning the happy path on the left, and returning as early as possible are concrete means to improve our code’s readability.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/2-nested-code/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/2-nested-code/main.go)
|
||||
|
||||
### Misusing init functions (#3)
|
||||
|
||||
|
|
@ -95,7 +91,7 @@ Init functions can lead to some issues:
|
|||
|
||||
We should be cautious with init functions. They can be helpful in some situations, however, such as defining static configuration. Otherwise, and in most cases, we should handle initializations through ad hoc functions.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/3-init-functions/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/3-init-functions/)
|
||||
|
||||
### Overusing getters and setters (#4)
|
||||
|
||||
|
|
@ -130,7 +126,7 @@ We should be cautious when creating abstractions in our code (abstractions shoul
|
|||
|
||||
Let’s not try to solve a problem abstractly but solve what has to be solved now. Last, but not least, if it’s unclear how an interface makes the code better, we should probably consider removing it to make our code simpler.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/5-interface-pollution/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/5-interface-pollution/)
|
||||
|
||||
### Interface on the producer side (#6)
|
||||
|
||||
|
|
@ -142,7 +138,7 @@ Interfaces are satisfied implicitly in Go, which tends to be a gamechanger compa
|
|||
|
||||
An interface should live on the consumer side in most cases. However, in particular contexts (for example, when we know—not foresee—that an abstraction will be helpful for consumers), we may want to have it on the producer side. If we do, we should strive to keep it as minimal as possible, increasing its reusability potential and making it more easily composable.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/6-interface-producer/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/6-interface-producer/)
|
||||
|
||||
### Returning interfaces (#7)
|
||||
|
||||
|
|
@ -160,7 +156,7 @@ In most cases, we shouldn’t return interfaces but concrete implementations. Ot
|
|||
|
||||
The `any` type can be helpful if there is a genuine need for accepting or returning any possible type (for instance, when it comes to marshaling or formatting). In general, we should avoid overgeneralizing the code we write at all costs. Perhaps a little bit of duplicated code might occasionally be better if it improves other aspects such as code expressiveness.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/8-any/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/8-any/main.go)
|
||||
|
||||
### Being confused about when to use generics (#9)
|
||||
|
||||
|
|
@ -170,7 +166,7 @@ The `any` type can be helpful if there is a genuine need for accepting or return
|
|||
|
||||
Read the full section [here](9-generics.md).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/9-generics/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/9-generics/main.go)
|
||||
|
||||
### Not being aware of the possible problems with type embedding (#10)
|
||||
|
||||
|
|
@ -206,7 +202,7 @@ If we decide to use type embedding, we need to keep two main constraints in mind
|
|||
|
||||
Using type embedding consciously by keeping these constraints in mind can help avoid boilerplate code with additional forwarding methods. However, let’s make sure we don’t do it solely for cosmetics and not promote elements that should remain hidden.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/10-type-embedding/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/10-type-embedding/main.go)
|
||||
|
||||
### Not using the functional options pattern (#11)
|
||||
|
||||
|
|
@ -266,7 +262,7 @@ func NewServer(addr string, opts ...Option) ( *http.Server, error) { <1>
|
|||
|
||||
The functional options pattern provides a handy and API-friendly way to handle options. Although the builder pattern can be a valid option, it has some minor downsides (having to pass a config struct that can be empty or a less handy way to handle error management) that tend to make the functional options pattern the idiomatic way to deal with these kind of problems in Go.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/11-functional-options/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/11-functional-options/)
|
||||
|
||||
### Project misorganization (project structure and package organization) (#12)
|
||||
|
||||
|
|
@ -293,7 +289,7 @@ Organizing a project isn’t straightforward, but following these rules should h
|
|||
|
||||
Also, bear in mind that naming a package after what it provides and not what it contains can be an efficient way to increase its expressiveness.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/13-utility-packages/stringset.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/13-utility-packages/stringset.go)
|
||||
|
||||
### Ignoring package name collisions (#14)
|
||||
|
||||
|
|
@ -362,7 +358,7 @@ We should also note the other integer literal representations:
|
|||
|
||||
We can also use an underscore character (_) as a separator for readability. For example, we can write 1 billion this way: `1_000_000_000`. We can also use the underscore character with other representations (for example, `0b00_00_01`).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/17-octal-literals/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/17-octal-literals/main.go)
|
||||
|
||||
### Neglecting integer overflows (#18)
|
||||
|
||||
|
|
@ -382,7 +378,7 @@ constant 2147483648 overflows int32
|
|||
|
||||
However, at run time, an integer overflow or underflow is silent; this does not lead to an application panic. It is essential to keep this behavior in mind, because it can lead to sneaky bugs (for example, an integer increment or addition of positive integers that leads to a negative result).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/18-integer-overflows)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/18-integer-overflows)
|
||||
|
||||
### Not understanding floating-points (#19)
|
||||
|
||||
|
|
@ -407,7 +403,7 @@ Because Go’s `float32` and `float64` types are approximations, we have to bear
|
|||
* When performing additions or subtractions, group operations with a similar order of magnitude for better accuracy.
|
||||
* To favor accuracy, if a sequence of operations requires addition, subtraction, multiplication, or division, perform the multiplication and division operations first.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/19-floating-points/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/19-floating-points/main.go)
|
||||
|
||||
### Not understanding slice length and capacity (#20)
|
||||
|
||||
|
|
@ -417,7 +413,7 @@ Because Go’s `float32` and `float64` types are approximations, we have to bear
|
|||
|
||||
Read the full section [here](20-slice.md).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/20-slice-length-cap/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/20-slice-length-cap/main.go)
|
||||
|
||||
### Inefficient slice initialization (#21)
|
||||
|
||||
|
|
@ -429,7 +425,7 @@ While initializing a slice using `make`, we can provide a length and an optional
|
|||
|
||||
Our options are to allocate a slice with either a given capacity or a given length. Of these two solutions, we have seen that the second tends to be slightly faster. But using a given capacity and append can be easier to implement and read in some contexts.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/21-slice-init/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/21-slice-init/main.go)
|
||||
|
||||
### Being confused about nil vs. empty slice (#22)
|
||||
|
||||
|
|
@ -445,7 +441,7 @@ In Go, there is a distinction between nil and empty slices. A nil slice is equal
|
|||
|
||||
The last option, `[]string{}`, should be avoided if we initialize the slice without elements. Finally, let’s check whether the libraries we use make the distinctions between nil and empty slices to prevent unexpected behaviors.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/22-nil-empty-slice/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/22-nil-empty-slice/)
|
||||
|
||||
### Not properly checking if a slice is empty (#23)
|
||||
|
||||
|
|
@ -457,7 +453,7 @@ To determine whether a slice has elements, we can either do it by checking if th
|
|||
|
||||
Meanwhile, when designing interfaces, we should avoid distinguishing nil and empty slices, which leads to subtle programming errors. When returning slices, it should make neither a semantic nor a technical difference if we return a nil or empty slice. Both should mean the same thing for the callers. This principle is the same with maps. To check if a map is empty, check its length, not whether it’s nil.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/23-checking-slice-empty/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/23-checking-slice-empty/main.go)
|
||||
|
||||
### Not making slice copies correctly (#24)
|
||||
|
||||
|
|
@ -467,7 +463,7 @@ Meanwhile, when designing interfaces, we should avoid distinguishing nil and emp
|
|||
|
||||
Copying elements from one slice to another is a reasonably frequent operation. When using copy, we must recall that the number of elements copied to the destination corresponds to the minimum between the two slices’ lengths. Also bear in mind that other alternatives exist to copy a slice, so we shouldn’t be surprised if we find them in a codebase.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/24-slice-copy/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/24-slice-copy/main.go)
|
||||
|
||||
### Unexpected side effects using slice append (#25)
|
||||
|
||||
|
|
@ -481,7 +477,7 @@ When using slicing, we must remember that we can face a situation leading to uni
|
|||
|
||||
`s[low:high:max]` (full slice expression): This statement creates a slice similar to the one created with `s[low:high]`, except that the resulting slice’s capacity is equal to `max - low`.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/25-slice-append/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/25-slice-append/main.go)
|
||||
|
||||
### Slices and memory leaks (#26)
|
||||
|
||||
|
|
@ -493,13 +489,13 @@ When using slicing, we must remember that we can face a situation leading to uni
|
|||
|
||||
Remember that slicing a large slice or array can lead to potential high memory consumption. The remaining space won’t be reclaimed by the GC, and we can keep a large backing array despite using only a few elements. Using a slice copy is the solution to prevent such a case.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/capacity-leak)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/capacity-leak)
|
||||
|
||||
#### Slice and pointers
|
||||
|
||||
When we use the slicing operation with pointers or structs with pointer fields, we need to know that the GC won’t reclaim these elements. In that case, the two options are to either perform a copy or explicitly mark the remaining elements or their fields to `nil`.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/slice-pointers)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/slice-pointers)
|
||||
|
||||
### Inefficient map initialization (#27)
|
||||
|
||||
|
|
@ -511,7 +507,7 @@ A map provides an unordered collection of key-value pairs in which all the keys
|
|||
|
||||
If we know up front the number of elements a map will contain, we should create it by providing an initial size. Doing this avoids potential map growth, which is quite heavy computation-wise because it requires reallocating enough space and rebalancing all the elements.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/27-map-init/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/27-map-init/main_test.go)
|
||||
|
||||
### Maps and memory leaks (#28)
|
||||
|
||||
|
|
@ -521,7 +517,7 @@ If we know up front the number of elements a map will contain, we should create
|
|||
|
||||
Read the full section [here](28-maps-memory-leaks.md).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/28-map-memory-leak/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/28-map-memory-leak/main.go)
|
||||
|
||||
### Comparing values incorrectly (#29)
|
||||
|
||||
|
|
@ -549,7 +545,7 @@ If performance is crucial at run time, implementing our custom method might be t
|
|||
One additional note: we must remember that the standard library has some existing comparison methods. For example, we can use the optimized `bytes.Compare` function to compare two slices of bytes. Before implementing a custom method, we need to make sure we don’t reinvent the wheel.
|
||||
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/29-comparing-values/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/29-comparing-values/main.go)
|
||||
|
||||
## Control Structures
|
||||
|
||||
|
|
@ -572,7 +568,7 @@ Compared to a classic for `loop`, a `range` loop is a convenient way to iterate
|
|||
|
||||
Yet, we should remember that the value element in a range loop is a copy. Therefore, if the value is a struct we need to mutate, we will only update the copy, not the element itself, unless the value or field we modify is a pointer. The favored options are to access the element via the index using a range loop or a classic for loop.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/30-range-loop-element-copied/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/30-range-loop-element-copied/)
|
||||
|
||||
### Ignoring how arguments are evaluated in `range` loops (channels and arrays) (#31)
|
||||
|
||||
|
|
@ -594,7 +590,7 @@ for i, v := range a {
|
|||
|
||||
This code updates the last index to 10. However, if we run this code, it does not print 10; it prints 2.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/31-range-loop-arg-evaluation/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/31-range-loop-arg-evaluation/)
|
||||
|
||||
### Ignoring the impacts of using pointer elements in `range` loops (#32)
|
||||
|
||||
|
|
@ -604,7 +600,7 @@ This code updates the last index to 10. However, if we run this code, it does no
|
|||
|
||||
When iterating over a data structure using a `range` loop, we must recall that all the values are assigned to a unique variable with a single unique address. Therefore, if we store a pointer referencing this variable during each iteration, we will end up in a situation where we store the same pointer referencing the same element: the latest one. We can overcome this issue by forcing the creation of a local variable in the loop’s scope or creating a pointer referencing a slice element via its index. Both solutions are fine.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/32-range-loop-pointers/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/32-range-loop-pointers/)
|
||||
|
||||
### Making wrong assumptions during map iterations (ordering and map insert during iteration) (#33)
|
||||
|
||||
|
|
@ -619,7 +615,7 @@ When iterating over a data structure using a `range` loop, we must recall that a
|
|||
|
||||
<!-- TODO -->
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/33-map-iteration/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/33-map-iteration/main.go)
|
||||
|
||||
### Ignoring how the `break` statement works (#34)
|
||||
|
||||
|
|
@ -662,7 +658,7 @@ loop:
|
|||
|
||||
Here, we associate the `loop` label with the `for` loop. Then, because we provide the `loop` label to the `break` statement, it breaks the loop, not the switch. Therefore, this new version will print `0 1 2`, as we expected.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/34-break/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/34-break/main.go)
|
||||
|
||||
### Using `defer` inside a loop (#35)
|
||||
|
||||
|
|
@ -719,7 +715,7 @@ func readFile(path string) error {
|
|||
|
||||
Another solution is to make the `readFile` function a closure but intrinsically, this remains the same solution: adding another surrounding function to execute the `defer` calls during each iteration.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/35-defer-loop/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/35-defer-loop/main.go)
|
||||
|
||||
## Strings
|
||||
|
||||
|
|
@ -738,7 +734,7 @@ As runes are everywhere in Go, it's important to understand the following:
|
|||
* Using UTF-8, a Unicode code point can be encoded into 1 to 4 bytes.
|
||||
* Using `len()` on a string in Go returns the number of bytes, not the number of runes.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/36-rune/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/36-rune/main.go)
|
||||
|
||||
### Inaccurate string iteration (#37)
|
||||
|
||||
|
|
@ -810,7 +806,7 @@ r := []rune(s)[4]
|
|||
fmt.Printf("%c\n", r) // o
|
||||
```
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/37-string-iteration/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/37-string-iteration/main.go)
|
||||
|
||||
### Misusing trim functions (#38)
|
||||
|
||||
|
|
@ -832,7 +828,7 @@ Conversely, `strings.TrimLeft` removes all the leading runes contained in a set.
|
|||
|
||||
On the other side, `strings.TrimSuffix` / `strings.TrimPrefix` returns a string without the provided trailing suffix / prefix.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/38-trim/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/38-trim/main.go)
|
||||
|
||||
### Under-optimized strings concatenation (#39)
|
||||
|
||||
|
|
@ -902,7 +898,7 @@ As we can see, the latest version is by far the most efficient: 99% faster than
|
|||
|
||||
`strings.Builder` is the recommended solution to concatenate a list of strings. Usually, this solution should be used within a loop. Indeed, if we just have to concatenate a few strings (such as a name and a surname), using `strings.Builder` is not recommended as doing so will make the code a bit less readable than using the `+=` operator or `fmt.Sprintf`.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/39-string-concat/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/39-string-concat/)
|
||||
|
||||
### Useless string conversions (#40)
|
||||
|
||||
|
|
@ -914,7 +910,7 @@ When choosing to work with a string or a `[]byte`, most programmers tend to favo
|
|||
|
||||
When we’re wondering whether we should work with strings or `[]byte`, let’s recall that working with `[]byte` isn’t necessarily less convenient. Indeed, all the exported functions of the strings package also have alternatives in the `bytes` package: `Split`, `Count`, `Contains`, `Index`, and so on. Hence, whether we’re doing I/O or not, we should first check whether we could implement a whole workflow using bytes instead of strings and avoid the price of additional conversions.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/40-string-conversion/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/40-string-conversion/main.go)
|
||||
|
||||
### Substring and memory leaks (#41)
|
||||
|
||||
|
|
@ -926,7 +922,7 @@ In mistake [#26, “Slices and memory leaks,”](#slice-and-memory-leaks--26-) w
|
|||
|
||||
We need to keep two things in mind while using the substring operation in Go. First, the interval provided is based on the number of bytes, not the number of runes. Second, a substring operation may lead to a memory leak as the resulting substring will share the same backing array as the initial string. The solutions to prevent this case from happening are to perform a string copy manually or to use `strings.Clone` from Go 1.18.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/41-substring-memory-leak/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/41-substring-memory-leak/main.go)
|
||||
|
||||
## Functions and Methods
|
||||
|
||||
|
|
@ -970,7 +966,7 @@ A receiver _should_ be a value
|
|||
|
||||
Of course, it’s impossible to be exhaustive, as there will always be edge cases, but this section’s goal was to provide guidance to cover most cases. By default, we can choose to go with a value receiver unless there’s a good reason not to do so. In doubt, we should use a pointer receiver.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/42-receiver/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/42-receiver/)
|
||||
|
||||
### Never using named result parameters (#43)
|
||||
|
||||
|
|
@ -993,7 +989,7 @@ In this example, we attach a name to the result parameter: `b`. When we call ret
|
|||
|
||||
In some cases, named result parameters can also increase readability: for example, if two parameters have the same type. In other cases, they can also be used for convenience. Therefore, we should use named result parameters sparingly when there’s a clear benefit.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/43-named-result-parameters/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/43-named-result-parameters/main.go)
|
||||
|
||||
### Unintended side effects with named result parameters (#44)
|
||||
|
||||
|
|
@ -1024,7 +1020,7 @@ The error might not be obvious at first glance. Here, the error returned in the
|
|||
|
||||
When using named result parameters, we must recall that each parameter is initialized to its zero value. As we have seen in this section, this can lead to subtle bugs that aren’t always straightforward to spot while reading code. Therefore, let’s remain cautious when using named result parameters, to avoid potential side effects.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/44-side-effects-named-result-parameters/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/44-side-effects-named-result-parameters/main.go)
|
||||
|
||||
### Returning a nil receiver (#45)
|
||||
|
||||
|
|
@ -1034,7 +1030,7 @@ When using named result parameters, we must recall that each parameter is initia
|
|||
|
||||
<!-- TODO -->
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/45-nil-receiver/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/45-nil-receiver/main.go)
|
||||
|
||||
### Using a filename as a function input (#46)
|
||||
|
||||
|
|
@ -1044,7 +1040,7 @@ When using named result parameters, we must recall that each parameter is initia
|
|||
|
||||
Accepting a filename as a function input to read from a file should, in most cases, be considered a code smell (except in specific functions such as `os.Open`). Indeed, it makes unit tests more complex because we may have to create multiple files. It also reduces the reusability of a function (although not all functions are meant to be reused). Using the `io.Reader` interface abstracts the data source. Regardless of whether the input is a file, a string, an HTTP request, or a gRPC request, the implementation can be reused and easily tested.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/46-function-input/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/46-function-input/)
|
||||
|
||||
### Ignoring how `defer` arguments and receivers are evaluated (argument evaluation, pointer, and value receivers) (#47)
|
||||
|
||||
|
|
@ -1129,7 +1125,7 @@ Here, we wrap the calls to both `notify` and `incrementCounter` within a closure
|
|||
|
||||
Let's also note this behavior applies with method receiver: the receiver is evaluated immediately.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/47-defer-evaluation/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/47-defer-evaluation/)
|
||||
|
||||
## Error Management
|
||||
|
||||
|
|
@ -1162,7 +1158,7 @@ main.main()
|
|||
|
||||
Panicking in Go should be used sparingly. There are two prominent cases, one to signal a programmer error (e.g., [`sql.Register`](https://cs.opensource.google/go/go/+/refs/tags/go1.20.7:src/database/sql/sql.go;l=44) that panics if the driver is `nil` or has already been register) and another where our application fails to create a mandatory dependency. Hence, exceptional conditions that lead us to stop the application. In most other cases, error management should be done with a function that returns a proper error type as the last return argument.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/48-panic/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/48-panic/main.go)
|
||||
|
||||
### Ignoring when to wrap an error (#49)
|
||||
|
||||
|
|
@ -1177,7 +1173,7 @@ Since Go 1.13, the %w directive allows us to wrap errors conveniently. Error wra
|
|||
|
||||
When handling an error, we can decide to wrap it. Wrapping is about adding additional context to an error and/or marking an error as a specific type. If we need to mark an error, we should create a custom error type. However, if we just want to add extra context, we should use fmt.Errorf with the %w directive as it doesn’t require creating a new error type. Yet, error wrapping creates potential coupling as it makes the source error available for the caller. If we want to prevent it, we shouldn’t use error wrapping but error transformation, for example, using fmt.Errorf with the %v directive.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/49-error-wrapping/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/49-error-wrapping/main.go)
|
||||
|
||||
### Comparing an error type inaccurately (#50)
|
||||
|
||||
|
|
@ -1187,7 +1183,7 @@ When handling an error, we can decide to wrap it. Wrapping is about adding addit
|
|||
|
||||
<!-- TODO -->
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/50-compare-error-type/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/50-compare-error-type/main.go)
|
||||
|
||||
### Comparing an error value inaccurately (#51)
|
||||
|
||||
|
|
@ -1210,7 +1206,7 @@ In general, the convention is to start with `Err` followed by the error type: he
|
|||
|
||||
If we use error wrapping in our application with the `%w` directive and `fmt.Errorf`, checking an error against a specific value should be done using `errors.Is` instead of `==`. Thus, even if the sentinel error is wrapped, `errors.Is` can recursively unwrap it and compare each error in the chain against the provided value.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/51-comparing-error-value/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/51-comparing-error-value/main.go)
|
||||
|
||||
### Handling an error twice (#52)
|
||||
|
||||
|
|
@ -1222,7 +1218,7 @@ Handling an error multiple times is a mistake made frequently by developers, not
|
|||
|
||||
Let's remind us that handling an error should be done only once. Logging an error is handling an error. Hence, we should either log or return an error. By doing this, we simplify our code and gain better insights into the error situation. Using error wrapping is the most convenient approach as it allows us to propagate the source error and add context to an error.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/52-handling-error-twice/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/52-handling-error-twice/main.go)
|
||||
|
||||
### Not handling an error (#53)
|
||||
|
||||
|
|
@ -1230,7 +1226,7 @@ Let's remind us that handling an error should be done only once. Logging an erro
|
|||
|
||||
Ignoring an error, whether during a function call or in a `defer` function, should be done explicitly using the blank identifier. Otherwise, future readers may be confused about whether it was intentional or a miss.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/53-not-handling-error/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/53-not-handling-error/main.go)
|
||||
|
||||
### Not handling `defer` errors (#54)
|
||||
|
||||
|
|
@ -1267,7 +1263,7 @@ In terms of compilation and run time, this approach doesn’t change anything co
|
|||
_ = notify()
|
||||
```
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/54-defer-errors/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/54-defer-errors/main.go)
|
||||
|
||||
## Concurrency: Foundations
|
||||
|
||||
|
|
@ -1283,7 +1279,7 @@ _ = notify()
|
|||
|
||||
To be a proficient developer, you must acknowledge that concurrency isn’t always faster. Solutions involving parallelization of minimal workloads may not necessarily be faster than a sequential implementation. Benchmarking sequential versus concurrent solutions should be the way to validate assumptions.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/56-faster/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/56-faster/)
|
||||
|
||||
### Being puzzled about when to use channels or mutexes (#57)
|
||||
|
||||
|
|
@ -1299,7 +1295,7 @@ _ = notify()
|
|||
|
||||
Understanding the Go memory model and the underlying guarantees in terms of ordering and synchronization is essential to prevent possible data races and/or race conditions.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/58-races/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/58-races/)
|
||||
|
||||
### Not understanding the concurrency impacts of a workload type (#59)
|
||||
|
||||
|
|
@ -1307,7 +1303,7 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
|
|||
|
||||
When creating a certain number of goroutines, consider the workload type. Creating CPU-bound goroutines means bounding this number close to the `GOMAXPROCS` variable (based by default on the number of CPU cores on the host). Creating I/O-bound goroutines depends on other factors, such as the external system.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/59-workload-type/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/59-workload-type/main.go)
|
||||
|
||||
### Misunderstanding Go contexts (#60)
|
||||
|
||||
|
|
@ -1315,7 +1311,7 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
|
|||
|
||||
Go contexts are also one of the cornerstones of concurrency in Go. A context allows you to carry a deadline, a cancellation signal, and/or a list of keys-values.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/60-contexts/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/60-contexts/main.go)
|
||||
|
||||
## Concurrency: Practice
|
||||
|
||||
|
|
@ -1325,7 +1321,7 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
|
|||
|
||||
Understanding the conditions when a context can be canceled should matter when propagating it: for example, an HTTP handler canceling the context when the response has been sent.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/61-inappropriate-context/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/61-inappropriate-context/main.go)
|
||||
|
||||
### Starting a goroutine without knowing when to stop it (#62)
|
||||
|
||||
|
|
@ -1333,7 +1329,7 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
|
|||
|
||||
Avoiding leaks means being mindful that whenever a goroutine is started, you should have a plan to stop it eventually.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/62-starting-goroutine/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/62-starting-goroutine/)
|
||||
|
||||
### Not being careful with goroutines and loop variables (#63)
|
||||
|
||||
|
|
@ -1341,7 +1337,7 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
|
|||
|
||||
To avoid bugs with goroutines and loop variables, create local variables or call functions instead of closures.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/63-goroutines-loop-variables/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/63-goroutines-loop-variables/main.go)
|
||||
|
||||
### Expecting a deterministic behavior using select and channels (#64)
|
||||
|
||||
|
|
@ -1349,7 +1345,7 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
|
|||
|
||||
Understanding that `select` with multiple channels chooses the case randomly if multiple options are possible prevents making wrong assumptions that can lead to subtle concurrency bugs.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/64-select-behavior/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/64-select-behavior/main.go)
|
||||
|
||||
### Not using notification channels (#65)
|
||||
|
||||
|
|
@ -1363,7 +1359,7 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
|
|||
|
||||
Using nil channels should be part of your concurrency toolset because it allows you to _remove_ cases from `select` statements, for example.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/66-nil-channels/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/66-nil-channels/main.go)
|
||||
|
||||
### Being puzzled about channel size (#67)
|
||||
|
||||
|
|
@ -1379,7 +1375,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Being aware that string formatting may lead to calling existing functions means watching out for possible deadlocks and other data races.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/68-string-formatting/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/68-string-formatting/main.go)
|
||||
|
||||
### Creating data races with append (#69)
|
||||
|
||||
|
|
@ -1387,7 +1383,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Calling `append` isn’t always data-race-free; hence, it shouldn’t be used concurrently on a shared slice.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/69-data-race-append/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/69-data-race-append/main.go)
|
||||
|
||||
### Using mutexes inaccurately with slices and maps (#70)
|
||||
|
||||
|
|
@ -1395,7 +1391,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Remembering that slices and maps are pointers can prevent common data races.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/70-mutex-slices-maps/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/70-mutex-slices-maps/main.go)
|
||||
|
||||
### Misusing `sync.WaitGroup` (#71)
|
||||
|
||||
|
|
@ -1403,7 +1399,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
To accurately use `sync.WaitGroup`, call the `Add` method before spinning up goroutines.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/71-wait-group/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/71-wait-group/main.go)
|
||||
|
||||
### Forgetting about `sync.Cond` (#72)
|
||||
|
||||
|
|
@ -1411,7 +1407,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
You can send repeated notifications to multiple goroutines with `sync.Cond`.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/72-cond/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/72-cond/main.go)
|
||||
|
||||
### Not using `errgroup` (#73)
|
||||
|
||||
|
|
@ -1419,7 +1415,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
You can synchronize a group of goroutines and handle errors and contexts with the `errgroup` package.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/73-errgroup/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/73-errgroup/main.go)
|
||||
|
||||
### Copying a `sync` type (#74)
|
||||
|
||||
|
|
@ -1427,7 +1423,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
`sync` types shouldn’t be copied.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/74-copying-sync/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/74-copying-sync/main.go)
|
||||
|
||||
## Standard Library
|
||||
|
||||
|
|
@ -1437,7 +1433,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Remain cautious with functions accepting a `time.Duration`. Even though passing an integer is allowed, strive to use the time API to prevent any possible confusion.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/75-wrong-time-duration/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/75-wrong-time-duration/main.go)
|
||||
|
||||
### `time.After` and memory leaks (#76)
|
||||
|
||||
|
|
@ -1445,7 +1441,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Avoiding calls to `time.After` in repeated functions (such as loops or HTTP handlers) can avoid peak memory consumption. The resources created by `time.After` are released only when the timer expires.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/76-time-after/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/76-time-after/main.go)
|
||||
|
||||
### JSON handling common mistakes (#77)
|
||||
|
||||
|
|
@ -1453,19 +1449,19 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Be careful about using embedded fields in Go structs. Doing so may lead to sneaky bugs like an embedded time.Time field implementing the `json.Marshaler` interface, hence overriding the default marshaling behavior.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/type-embedding/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/type-embedding/main.go)
|
||||
|
||||
* JSON and the monotonic clock
|
||||
|
||||
When comparing two `time.Time` structs, recall that `time.Time` contains both a wall clock and a monotonic clock, and the comparison using the == operator is done on both clocks.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/monotonic-clock/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/monotonic-clock/main.go)
|
||||
|
||||
* Map of `any`
|
||||
|
||||
To avoid wrong assumptions when you provide a map while unmarshaling JSON data, remember that numerics are converted to `float64` by default.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/map-any/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/map-any/main.go)
|
||||
|
||||
### Common SQL mistakes (#78)
|
||||
|
||||
|
|
@ -1473,7 +1469,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Call the `Ping` or `PingContext` method if you need to test your configuration and make sure a database is reachable.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/sql-open)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/sql-open)
|
||||
|
||||
* Forgetting about connections pooling
|
||||
|
||||
|
|
@ -1483,19 +1479,19 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Using SQL prepared statements makes queries more efficient and more secure.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/prepared-statements)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/prepared-statements)
|
||||
|
||||
* Mishandling null values
|
||||
|
||||
Deal with nullable columns in tables using pointers or `sql.NullXXX` types.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/null-values/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/null-values/main.go)
|
||||
|
||||
* Not handling rows iteration errors
|
||||
|
||||
Call the `Err` method of `sql.Rows` after row iterations to ensure that you haven’t missed an error while preparing the next row.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/rows-iterations-errors)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/rows-iterations-errors)
|
||||
|
||||
### Not closing transient resources (HTTP body, `sql.Rows`, and `os.File`) (#79)
|
||||
|
||||
|
|
@ -1503,7 +1499,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Eventually close all structs implementing `io.Closer` to avoid possible leaks.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/79-closing-resources/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/79-closing-resources/)
|
||||
|
||||
### Forgetting the return statement after replying to an HTTP request (#80)
|
||||
|
||||
|
|
@ -1511,7 +1507,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
To avoid unexpected behaviors in HTTP handler implementations, make sure you don’t miss the `return` statement if you want a handler to stop after `http.Error`.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/80-http-return/main.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/80-http-return/main.go)
|
||||
|
||||
### Using the default HTTP client and server (#81)
|
||||
|
||||
|
|
@ -1519,7 +1515,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
For production-grade applications, don’t use the default HTTP client and server implementations. These implementations are missing timeouts and behaviors that should be mandatory in production.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/81-default-http-client-server/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/81-default-http-client-server/)
|
||||
|
||||
## Testing
|
||||
|
||||
|
|
@ -1529,7 +1525,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Categorizing tests using build flags, environment variables, or short mode makes the testing process more efficient. You can create test categories using build flags or environment variables (for example, unit versus integration tests) and differentiate short from long-running tests to decide which kinds of tests to execute.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/82-categorizing-tests/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/82-categorizing-tests/)
|
||||
|
||||
### Not enabling the race flag (#83)
|
||||
|
||||
|
|
@ -1549,7 +1545,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Table-driven tests are an efficient way to group a set of similar tests to prevent code duplication and make future updates easier to handle.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/85-table-driven-tests/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/85-table-driven-tests/main_test.go)
|
||||
|
||||
### Sleeping in unit tests (#86)
|
||||
|
||||
|
|
@ -1557,7 +1553,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Avoid sleeps using synchronization to make a test less flaky and more robust. If synchronization isn’t possible, consider a retry approach.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/86-sleeping/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/86-sleeping/main_test.go)
|
||||
|
||||
### Not dealing with the time API efficiently (#87)
|
||||
|
||||
|
|
@ -1565,17 +1561,17 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Understanding how to deal with functions using the time API is another way to make a test less flaky. You can use standard techniques such as handling the time as part of a hidden dependency or asking clients to provide it.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/87-time-api/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/87-time-api/)
|
||||
|
||||
### Not using testing utility packages (`httptest` and `iotest`) (#88)
|
||||
|
||||
* The `httptest` package is helpful for dealing with HTTP applications. It provides a set of utilities to test both clients and servers.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/httptest/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/httptest/main_test.go)
|
||||
|
||||
* The `iotest` package helps write io.Reader and test that an application is tolerant to errors.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/iotest/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/iotest/main_test.go)
|
||||
|
||||
### Writing inaccurate benchmarks (#89)
|
||||
|
||||
|
|
@ -1591,7 +1587,7 @@ You should have a good reason to specify a channel size other than one for buffe
|
|||
|
||||
Read the full section [here](89-benchmarks.md).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/89-benchmark/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/89-benchmark/)
|
||||
|
||||
### Not exploring all the Go testing features (#90)
|
||||
|
||||
|
|
@ -1603,19 +1599,19 @@ Read the full section [here](89-benchmarks.md).
|
|||
|
||||
Place unit tests in a different package to enforce writing tests that focus on an exposed behavior, not internals.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/different-package/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/different-package/main_test.go)
|
||||
|
||||
* Utility functions
|
||||
|
||||
Handling errors using the `*testing.T` variable instead of the classic `if err != nil` makes code shorter and easier to read.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/utility-function/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/utility-function/main_test.go)
|
||||
|
||||
* Setup and teardown
|
||||
|
||||
You can use setup and teardown functions to configure a complex environment, such as in the case of integration tests.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/setup-teardown/main_test.go)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/setup-teardown/main_test.go)
|
||||
|
||||
### Not using fuzzing (community mistake)
|
||||
|
||||
|
|
@ -1637,19 +1633,19 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
|
|||
|
||||
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.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/cache-line/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/cache-line/)
|
||||
|
||||
* Slice of structs vs. struct of slices
|
||||
|
||||
<!-- TODO -->
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/slice-structs/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/slice-structs/)
|
||||
|
||||
* 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.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/predictability/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/predictability/)
|
||||
|
||||
* Cache placement policy
|
||||
|
||||
|
|
@ -1661,7 +1657,7 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
|
|||
|
||||
Knowing that lower levels of CPU caches aren’t shared across all the cores helps avoid performance-degrading patterns such as false sharing while writing concurrency code. Sharing memory is an illusion.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/92-false-sharing/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/92-false-sharing/)
|
||||
|
||||
### Not taking into account instruction-level parallelism (#93)
|
||||
|
||||
|
|
@ -1669,7 +1665,7 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
|
|||
|
||||
Use instruction-level parallelism (ILP) to optimize specific parts of your code to allow a CPU to execute as many parallel instructions as possible. Identifying data hazards is one of the main steps.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/93-instruction-level-parallelism/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/93-instruction-level-parallelism/)
|
||||
|
||||
### Not being aware of data alignment (#94)
|
||||
|
||||
|
|
@ -1677,7 +1673,7 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
|
|||
|
||||
You can avoid common mistakes by remembering that in Go, basic types are aligned with their own size. For example, keep in mind that reorganizing the fields of a struct by size in descending order can lead to more compact structs (less memory allocation and potentially a better spatial locality).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/94-data-alignment/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/94-data-alignment/)
|
||||
|
||||
### Not understanding stack vs. heap (#95)
|
||||
|
||||
|
|
@ -1685,7 +1681,7 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
|
|||
|
||||
Understanding the fundamental differences between heap and stack should also be part of your core knowledge when optimizing a Go application. Stack allocations are almost free, whereas heap allocations are slower and rely on the GC to clean the memory.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/95-stack-heap/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/95-stack-heap/)
|
||||
|
||||
### Not knowing how to reduce allocations (API change, compiler optimizations, and `sync.Pool`) (#96)
|
||||
|
||||
|
|
@ -1693,7 +1689,7 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
|
|||
|
||||
Reducing allocations is also an essential aspect of optimizing a Go application. This can be done in different ways, such as designing the API carefully to prevent sharing up, understanding the common Go compiler optimizations, and using `sync.Pool`.
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/96-reduce-allocations/)
|
||||
[Source code :simple-github:](https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/96-reduce-allocations/)
|
||||
|
||||
### Not relying on inlining (#97)
|
||||
|
||||
|
|
|
|||
|
|
@ -84,4 +84,7 @@ markdown_extensions:
|
|||
- attr_list
|
||||
- md_in_html
|
||||
- footnotes
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
copyright: Copyright © 2022 - 2023 Teiva Harsanyi
|
||||
|
|
|
|||
194
site/index.html
194
site/index.html
|
|
@ -2609,10 +2609,6 @@
|
|||
<summary>Warning</summary>
|
||||
<p>You're currently viewing a new version that I'm enriching with significantly more content. Yet, this version is still under development; please be gentle if you find an issue, and feel free to create a PR.</p>
|
||||
</details>
|
||||
<!-- TODO Include full excerpts -->
|
||||
|
||||
<!-- TODO Include chapter-1.md -->
|
||||
|
||||
<p><a class="glightbox" href="img/inside-cover.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="img/inside-cover.png" /></a></p>
|
||||
<h2 id="code-and-project-organization">Code and Project Organization</h2>
|
||||
<h3 id="unintended-variable-shadowing-1">Unintended variable shadowing (#1)</h3>
|
||||
|
|
@ -2621,7 +2617,7 @@
|
|||
<p>Avoiding shadowed variables can help prevent mistakes like referencing the wrong variable or confusing readers.</p>
|
||||
</details>
|
||||
<p>Variable shadowing occurs when a variable name is redeclared in an inner block, but this practice is prone to mistakes. Imposing a rule to forbid shadowed variables depends on personal taste. For example, sometimes it can be convenient to reuse an existing variable name like <code>err</code> for errors. Yet, in general, we should remain cautious because we now know that we can face a scenario where the code compiles, but the variable that receives the value is not the one expected.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/1-variable-shadowing/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/1-variable-shadowing/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="unnecessary-nested-code-2">Unnecessary nested code (#2)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2662,7 +2658,7 @@
|
|||
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="c1">// ...</span>
|
||||
</span></code></pre></div>
|
||||
<p>Writing readable code is an important challenge for every developer. Striving to reduce the number of nested blocks, aligning the happy path on the left, and returning as early as possible are concrete means to improve our code’s readability.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/2-nested-code/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/2-nested-code/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="misusing-init-functions-3">Misusing init functions (#3)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2676,7 +2672,7 @@
|
|||
<li>If the initialization requires us to set a state, that has to be done through global variables.</li>
|
||||
</ul>
|
||||
<p>We should be cautious with init functions. They can be helpful in some situations, however, such as defining static configuration. Otherwise, and in most cases, we should handle initializations through ad hoc functions.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/3-init-functions/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/3-init-functions/">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="overusing-getters-and-setters-4">Overusing getters and setters (#4)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2700,7 +2696,7 @@ What’s the main problem if we overuse interfaces? The answer is that they make
|
|||
<p>Don’t design with interfaces, discover them.</p>
|
||||
</div>
|
||||
<p>Let’s not try to solve a problem abstractly but solve what has to be solved now. Last, but not least, if it’s unclear how an interface makes the code better, we should probably consider removing it to make our code simpler.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/5-interface-pollution/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/5-interface-pollution/">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="interface-on-the-producer-side-6">Interface on the producer side (#6)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2708,7 +2704,7 @@ What’s the main problem if we overuse interfaces? The answer is that they make
|
|||
</details>
|
||||
<p>Interfaces are satisfied implicitly in Go, which tends to be a gamechanger compared to languages with an explicit implementation. In most cases, the approach to follow is similar to what we described in the previous section: <em>abstractions should be discovered, not created</em>. This means that it’s not up to the producer to force a given abstraction for all the clients. Instead, it’s up to the client to decide whether it needs some form of abstraction and then determine the best abstraction level for its needs.</p>
|
||||
<p>An interface should live on the consumer side in most cases. However, in particular contexts (for example, when we know—not foresee—that an abstraction will be helpful for consumers), we may want to have it on the producer side. If we do, we should strive to keep it as minimal as possible, increasing its reusability potential and making it more easily composable.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/6-interface-producer/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/6-interface-producer/">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="returning-interfaces-7">Returning interfaces (#7)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2721,14 +2717,14 @@ What’s the main problem if we overuse interfaces? The answer is that they make
|
|||
<p>Only use <code>any</code> if you need to accept or return any possible type, such as <code>json.Marshal</code>. Otherwise, <code>any</code> doesn’t provide meaningful information and can lead to compile-time issues by allowing a caller to call methods with any data type.</p>
|
||||
</details>
|
||||
<p>The <code>any</code> type can be helpful if there is a genuine need for accepting or returning any possible type (for instance, when it comes to marshaling or formatting). In general, we should avoid overgeneralizing the code we write at all costs. Perhaps a little bit of duplicated code might occasionally be better if it improves other aspects such as code expressiveness.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/8-any/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/8-any/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="being-confused-about-when-to-use-generics-9">Being confused about when to use generics (#9)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Relying on generics and type parameters can prevent writing boilerplate code to factor out elements or behaviors. However, do not use type parameters prematurely, but only when you see a concrete need for them. Otherwise, they introduce unnecessary abstractions and complexity.</p>
|
||||
</details>
|
||||
<p>Read the full section <a href="9-generics/">here</a>.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/9-generics/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/9-generics/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="not-being-aware-of-the-possible-problems-with-type-embedding-10">Not being aware of the possible problems with type embedding (#10)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2754,7 +2750,7 @@ promoted to <code>Foo</code>. Therefore, Baz becomes available from Foo.</p>
|
|||
<li>It shouldn’t promote data (fields) or a behavior (methods) we want to hide from the outside: for example, if it allows clients to access a locking behavior that should remain private to the struct.</li>
|
||||
</ul>
|
||||
<p>Using type embedding consciously by keeping these constraints in mind can help avoid boilerplate code with additional forwarding methods. However, let’s make sure we don’t do it solely for cosmetics and not promote elements that should remain hidden.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/10-type-embedding/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/10-type-embedding/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="not-using-the-functional-options-pattern-11">Not using the functional options pattern (#11)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2808,7 +2804,7 @@ promoted to <code>Foo</code>. Therefore, Baz becomes available from Foo.</p>
|
|||
</span><span id="__span-5-40"><a id="__codelineno-5-40" name="__codelineno-5-40" href="#__codelineno-5-40"></a><span class="p">}</span>
|
||||
</span></code></pre></div>
|
||||
<p>The functional options pattern provides a handy and API-friendly way to handle options. Although the builder pattern can be a valid option, it has some minor downsides (having to pass a config struct that can be empty or a less handy way to handle error management) that tend to make the functional options pattern the idiomatic way to deal with these kind of problems in Go.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/11-functional-options/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/11-functional-options/">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="project-misorganization-project-structure-and-package-organization-12">Project misorganization (project structure and package organization) (#12)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2826,7 +2822,7 @@ Granularity is another essential thing to consider. We should avoid having dozen
|
|||
<p>Naming is a critical piece of application design. Creating packages such as <code>common</code>, <code>util</code>, and <code>shared</code> doesn’t bring much value for the reader. Refactor such packages into meaningful and specific package names.</p>
|
||||
</details>
|
||||
<p>Also, bear in mind that naming a package after what it provides and not what it contains can be an efficient way to increase its expressiveness.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/13-utility-packages/stringset.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/13-utility-packages/stringset.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="ignoring-package-name-collisions-14">Ignoring package name collisions (#14)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2878,7 +2874,7 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
<li><em>Imaginary</em>—Uses an <code>i</code> suffix (for example, <code>3i</code>)</li>
|
||||
</ul>
|
||||
<p>We can also use an underscore character (_) as a separator for readability. For example, we can write 1 billion this way: <code>1_000_000_000</code>. We can also use the underscore character with other representations (for example, <code>0b00_00_01</code>).</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/17-octal-literals/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/17-octal-literals/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="neglecting-integer-overflows-18">Neglecting integer overflows (#18)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2890,7 +2886,7 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
<div class="language-shell highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a>constant<span class="w"> </span><span class="m">2147483648</span><span class="w"> </span>overflows<span class="w"> </span>int32
|
||||
</span></code></pre></div>
|
||||
<p>However, at run time, an integer overflow or underflow is silent; this does not lead to an application panic. It is essential to keep this behavior in mind, because it can lead to sneaky bugs (for example, an integer increment or addition of positive integers that leads to a negative result).</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/18-integer-overflows">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/18-integer-overflows">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="not-understanding-floating-points-19">Not understanding floating-points (#19)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2908,14 +2904,14 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
<li>When performing additions or subtractions, group operations with a similar order of magnitude for better accuracy.</li>
|
||||
<li>To favor accuracy, if a sequence of operations requires addition, subtraction, multiplication, or division, perform the multiplication and division operations first.</li>
|
||||
</ul>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/19-floating-points/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/19-floating-points/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="not-understanding-slice-length-and-capacity-20">Not understanding slice length and capacity (#20)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Understanding the difference between slice length and capacity should be part of a Go developer’s core knowledge. The slice length is the number of available elements in the slice, whereas the slice capacity is the number of elements in the backing array.</p>
|
||||
</details>
|
||||
<p>Read the full section <a href="20-slice/">here</a>.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/20-slice-length-cap/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/20-slice-length-cap/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="inefficient-slice-initialization-21">Inefficient slice initialization (#21)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2923,7 +2919,7 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
</details>
|
||||
<p>While initializing a slice using <code>make</code>, we can provide a length and an optional capacity. Forgetting to pass an appropriate value for both of these parameters when it makes sense is a widespread mistake. Indeed, it can lead to multiple copies and additional effort for the GC to clean the temporary backing arrays. Performance-wise, there’s no good reason not to give the Go runtime a helping hand.</p>
|
||||
<p>Our options are to allocate a slice with either a given capacity or a given length. Of these two solutions, we have seen that the second tends to be slightly faster. But using a given capacity and append can be easier to implement and read in some contexts.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/21-slice-init/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/21-slice-init/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="being-confused-about-nil-vs-empty-slice-22">Being confused about nil vs. empty slice (#22)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2936,7 +2932,7 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
<li><code>make([]string, length)</code> if the future length is known</li>
|
||||
</ul>
|
||||
<p>The last option, <code>[]string{}</code>, should be avoided if we initialize the slice without elements. Finally, let’s check whether the libraries we use make the distinctions between nil and empty slices to prevent unexpected behaviors.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/22-nil-empty-slice/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/22-nil-empty-slice/">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="not-properly-checking-if-a-slice-is-empty-23">Not properly checking if a slice is empty (#23)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2944,14 +2940,14 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
</details>
|
||||
<p>To determine whether a slice has elements, we can either do it by checking if the slice is nil or if its length is equal to 0. Checking the length is the best option to follow as it will cover both if the slice is empty or is the slice is nil.</p>
|
||||
<p>Meanwhile, when designing interfaces, we should avoid distinguishing nil and empty slices, which leads to subtle programming errors. When returning slices, it should make neither a semantic nor a technical difference if we return a nil or empty slice. Both should mean the same thing for the callers. This principle is the same with maps. To check if a map is empty, check its length, not whether it’s nil.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/23-checking-slice-empty/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/23-checking-slice-empty/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="not-making-slice-copies-correctly-24">Not making slice copies correctly (#24)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>To copy one slice to another using the <code>copy</code> built-in function, remember that the number of copied elements corresponds to the minimum between the two slice’s lengths.</p>
|
||||
</details>
|
||||
<p>Copying elements from one slice to another is a reasonably frequent operation. When using copy, we must recall that the number of elements copied to the destination corresponds to the minimum between the two slices’ lengths. Also bear in mind that other alternatives exist to copy a slice, so we shouldn’t be surprised if we find them in a codebase.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/24-slice-copy/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/24-slice-copy/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="unexpected-side-effects-using-slice-append-25">Unexpected side effects using slice append (#25)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2962,7 +2958,7 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
<summary>Note</summary>
|
||||
<p><code>s[low:high:max]</code> (full slice expression): This statement creates a slice similar to the one created with <code>s[low:high]</code>, except that the resulting slice’s capacity is equal to <code>max - low</code>.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/25-slice-append/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/25-slice-append/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="slices-and-memory-leaks-26">Slices and memory leaks (#26)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2970,10 +2966,10 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
</details>
|
||||
<h4 id="leaking-capacity">Leaking capacity</h4>
|
||||
<p>Remember that slicing a large slice or array can lead to potential high memory consumption. The remaining space won’t be reclaimed by the GC, and we can keep a large backing array despite using only a few elements. Using a slice copy is the solution to prevent such a case.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/capacity-leak">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/capacity-leak">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>
|
||||
<h4 id="slice-and-pointers">Slice and pointers</h4>
|
||||
<p>When we use the slicing operation with pointers or structs with pointer fields, we need to know that the GC won’t reclaim these elements. In that case, the two options are to either perform a copy or explicitly mark the remaining elements or their fields to <code>nil</code>.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/slice-pointers">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/26-slice-memory-leak/slice-pointers">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="inefficient-map-initialization-27">Inefficient map initialization (#27)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -2981,14 +2977,14 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
</details>
|
||||
<p>A map provides an unordered collection of key-value pairs in which all the keys are distinct. In Go, a map is based on the hash table data structure. Internally, a hash table is an array of buckets, and each bucket is a pointer to an array of key-value pairs.</p>
|
||||
<p>If we know up front the number of elements a map will contain, we should create it by providing an initial size. Doing this avoids potential map growth, which is quite heavy computation-wise because it requires reallocating enough space and rebalancing all the elements.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/27-map-init/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/27-map-init/main_test.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="maps-and-memory-leaks-28">Maps and memory leaks (#28)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>A map can always grow in memory, but it never shrinks. Hence, if it leads to some memory issues, you can try different options, such as forcing Go to recreate the map or using pointers.</p>
|
||||
</details>
|
||||
<p>Read the full section <a href="28-maps-memory-leaks/">here</a>.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/28-map-memory-leak/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/28-map-memory-leak/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="comparing-values-incorrectly-29">Comparing values incorrectly (#29)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3011,7 +3007,7 @@ Meanwhile, we should also look at golangci-lint (<a href="https://github.com/gol
|
|||
<p>If operands are not comparable (e.g., slices and maps), we have to use other options such as reflection. Reflection is a form of metaprogramming, and it refers to the ability of an application to introspect and modify its structure and behavior. For example, in Go, we can use <code>reflect.DeepEqual</code>. This function reports whether two elements are deeply equal by recursively traversing two values. The elements it accepts are basic types plus arrays, structs, slices, maps, pointers, interfaces, and functions. Yet, the main catch is the performance penalty.</p>
|
||||
<p>If performance is crucial at run time, implementing our custom method might be the best solution.
|
||||
One additional note: we must remember that the standard library has some existing comparison methods. For example, we can use the optimized <code>bytes.Compare</code> function to compare two slices of bytes. Before implementing a custom method, we need to make sure we don’t reinvent the wheel.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/29-comparing-values/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/29-comparing-values/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>
|
||||
<h2 id="control-structures">Control Structures</h2>
|
||||
<h3 id="ignoring-that-elements-are-copied-in-range-loops-30">Ignoring that elements are copied in <code>range</code> loops (#30)</h3>
|
||||
<details class="info" open="open">
|
||||
|
|
@ -3029,7 +3025,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</ul>
|
||||
<p>Compared to a classic for <code>loop</code>, a <code>range</code> loop is a convenient way to iterate over all the elements of one of these data structures, thanks to its concise syntax.</p>
|
||||
<p>Yet, we should remember that the value element in a range loop is a copy. Therefore, if the value is a struct we need to mutate, we will only update the copy, not the element itself, unless the value or field we modify is a pointer. The favored options are to access the element via the index using a range loop or a classic for loop.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/30-range-loop-element-copied/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/30-range-loop-element-copied/">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="ignoring-how-arguments-are-evaluated-in-range-loops-channels-and-arrays-31">Ignoring how arguments are evaluated in <code>range</code> loops (channels and arrays) (#31)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3045,14 +3041,14 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span><span id="__span-9-7"><a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a><span class="p">}</span>
|
||||
</span></code></pre></div>
|
||||
<p>This code updates the last index to 10. However, if we run this code, it does not print 10; it prints 2.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/31-range-loop-arg-evaluation/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/31-range-loop-arg-evaluation/">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="ignoring-the-impacts-of-using-pointer-elements-in-range-loops-32">Ignoring the impacts of using pointer elements in <code>range</code> loops (#32)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Using a local variable or accessing an element using an index, you can prevent mistakes while copying pointers inside a loop.</p>
|
||||
</details>
|
||||
<p>When iterating over a data structure using a <code>range</code> loop, we must recall that all the values are assigned to a unique variable with a single unique address. Therefore, if we store a pointer referencing this variable during each iteration, we will end up in a situation where we store the same pointer referencing the same element: the latest one. We can overcome this issue by forcing the creation of a local variable in the loop’s scope or creating a pointer referencing a slice element via its index. Both solutions are fine.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/32-range-loop-pointers/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/32-range-loop-pointers/">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="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) (#33)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3066,7 +3062,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</ul>
|
||||
<!-- TODO -->
|
||||
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/33-map-iteration/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/33-map-iteration/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="ignoring-how-the-break-statement-works-34">Ignoring how the <code>break</code> statement works (#34)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3098,7 +3094,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span><span id="__span-11-10"><a id="__codelineno-11-10" name="__codelineno-11-10" href="#__codelineno-11-10"></a><span class="w"> </span><span class="p">}</span>
|
||||
</span></code></pre></div>
|
||||
<p>Here, we associate the <code>loop</code> label with the <code>for</code> loop. Then, because we provide the <code>loop</code> label to the <code>break</code> statement, it breaks the loop, not the switch. Therefore, this new version will print <code>0 1 2</code>, as we expected.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/34-break/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/34-break/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-defer-inside-a-loop-35">Using <code>defer</code> inside a loop (#35)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3144,7 +3140,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span><span id="__span-13-20"><a id="__codelineno-13-20" name="__codelineno-13-20" href="#__codelineno-13-20"></a><span class="p">}</span>
|
||||
</span></code></pre></div>
|
||||
<p>Another solution is to make the <code>readFile</code> function a closure but intrinsically, this remains the same solution: adding another surrounding function to execute the <code>defer</code> calls during each iteration.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/35-defer-loop/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/35-defer-loop/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>
|
||||
<h2 id="strings">Strings</h2>
|
||||
<h3 id="not-understanding-the-concept-of-rune-36">Not understanding the concept of rune (#36)</h3>
|
||||
<details class="info" open="open">
|
||||
|
|
@ -3160,7 +3156,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<li>Using UTF-8, a Unicode code point can be encoded into 1 to 4 bytes.</li>
|
||||
<li>Using <code>len()</code> on a string in Go returns the number of bytes, not the number of runes.</li>
|
||||
</ul>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/36-rune/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/36-rune/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="inaccurate-string-iteration-37">Inaccurate string iteration (#37)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3210,7 +3206,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span><span id="__span-18-2"><a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a><span class="nx">r</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">[]</span><span class="nb">rune</span><span class="p">(</span><span class="nx">s</span><span class="p">)[</span><span class="mi">4</span><span class="p">]</span>
|
||||
</span><span id="__span-18-3"><a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">"%c\n"</span><span class="p">,</span><span class="w"> </span><span class="nx">r</span><span class="p">)</span><span class="w"> </span><span class="c1">// o</span>
|
||||
</span></code></pre></div>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/37-string-iteration/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/37-string-iteration/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="misusing-trim-functions-38">Misusing trim functions (#38)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3223,7 +3219,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<p><a class="glightbox" href="img/trim.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="img/trim.png" /></a></p>
|
||||
<p>Conversely, <code>strings.TrimLeft</code> removes all the leading runes contained in a set.</p>
|
||||
<p>On the other side, <code>strings.TrimSuffix</code> / <code>strings.TrimPrefix</code> returns a string without the provided trailing suffix / prefix.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/38-trim/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/38-trim/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="under-optimized-strings-concatenation-39">Under-optimized strings concatenation (#39)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3275,7 +3271,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span></code></pre></div>
|
||||
<p>As we can see, the latest version is by far the most efficient: 99% faster than v1 and 78% faster than v2.</p>
|
||||
<p><code>strings.Builder</code> is the recommended solution to concatenate a list of strings. Usually, this solution should be used within a loop. Indeed, if we just have to concatenate a few strings (such as a name and a surname), using <code>strings.Builder</code> is not recommended as doing so will make the code a bit less readable than using the <code>+=</code> operator or <code>fmt.Sprintf</code>.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/39-string-concat/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/39-string-concat/">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="useless-string-conversions-40">Useless string conversions (#40)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3283,7 +3279,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</details>
|
||||
<p>When choosing to work with a string or a <code>[]byte</code>, most programmers tend to favor strings for convenience. But most I/O is actually done with <code>[]byte</code>. For example, <code>io.Reader</code>, <code>io.Writer</code>, and <code>io.ReadAll</code> work with <code>[]byte</code>, not strings.</p>
|
||||
<p>When we’re wondering whether we should work with strings or <code>[]byte</code>, let’s recall that working with <code>[]byte</code> isn’t necessarily less convenient. Indeed, all the exported functions of the strings package also have alternatives in the <code>bytes</code> package: <code>Split</code>, <code>Count</code>, <code>Contains</code>, <code>Index</code>, and so on. Hence, whether we’re doing I/O or not, we should first check whether we could implement a whole workflow using bytes instead of strings and avoid the price of additional conversions.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/40-string-conversion/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/40-string-conversion/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="substring-and-memory-leaks-41">Substring and memory leaks (#41)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3291,7 +3287,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</details>
|
||||
<p>In mistake <a href="#slice-and-memory-leaks--26-">#26, “Slices and memory leaks,”</a> we saw how slicing a slice or array may lead to memory leak situations. This principle also applies to string and substring operations.</p>
|
||||
<p>We need to keep two things in mind while using the substring operation in Go. First, the interval provided is based on the number of bytes, not the number of runes. Second, a substring operation may lead to a memory leak as the resulting substring will share the same backing array as the initial string. The solutions to prevent this case from happening are to perform a string copy manually or to use <code>strings.Clone</code> from Go 1.18.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/41-substring-memory-leak/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/05-strings/41-substring-memory-leak/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>
|
||||
<h2 id="functions-and-methods">Functions and Methods</h2>
|
||||
<h3 id="not-knowing-which-type-of-receiver-to-use-42">Not knowing which type of receiver to use (#42)</h3>
|
||||
<details class="info" open="open">
|
||||
|
|
@ -3329,7 +3325,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<li>If the receiver is a basic type such as <code>int</code>, <code>float64</code>, or <code>string</code>.</li>
|
||||
</ul>
|
||||
<p>Of course, it’s impossible to be exhaustive, as there will always be edge cases, but this section’s goal was to provide guidance to cover most cases. By default, we can choose to go with a value receiver unless there’s a good reason not to do so. In doubt, we should use a pointer receiver.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/42-receiver/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/42-receiver/">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="never-using-named-result-parameters-43">Never using named result parameters (#43)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3344,7 +3340,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span></code></pre></div>
|
||||
<p>In this example, we attach a name to the result parameter: <code>b</code>. When we call return without arguments, it returns the current value of <code>b</code>.</p>
|
||||
<p>In some cases, named result parameters can also increase readability: for example, if two parameters have the same type. In other cases, they can also be used for convenience. Therefore, we should use named result parameters sparingly when there’s a clear benefit.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/43-named-result-parameters/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/43-named-result-parameters/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="unintended-side-effects-with-named-result-parameters-44">Unintended side effects with named result parameters (#44)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3367,7 +3363,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span></code></pre></div>
|
||||
<p>The error might not be obvious at first glance. Here, the error returned in the <code>if ctx.Err() != nil</code> scope is <code>err</code>. But we haven’t assigned any value to the <code>err</code> variable. It’s still assigned to the zero value of an <code>error</code> type: <code>nil</code>. Hence, this code will always return a nil error.</p>
|
||||
<p>When using named result parameters, we must recall that each parameter is initialized to its zero value. As we have seen in this section, this can lead to subtle bugs that aren’t always straightforward to spot while reading code. Therefore, let’s remain cautious when using named result parameters, to avoid potential side effects.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/44-side-effects-named-result-parameters/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/44-side-effects-named-result-parameters/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="returning-a-nil-receiver-45">Returning a nil receiver (#45)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3375,14 +3371,14 @@ One additional note: we must remember that the standard library has some existin
|
|||
</details>
|
||||
<!-- TODO -->
|
||||
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/45-nil-receiver/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/45-nil-receiver/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-a-filename-as-a-function-input-46">Using a filename as a function input (#46)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Designing functions to receive <code>io.Reader</code> types instead of filenames improves the reusability of a function and makes testing easier.</p>
|
||||
</details>
|
||||
<p>Accepting a filename as a function input to read from a file should, in most cases, be considered a code smell (except in specific functions such as <code>os.Open</code>). Indeed, it makes unit tests more complex because we may have to create multiple files. It also reduces the reusability of a function (although not all functions are meant to be reused). Using the <code>io.Reader</code> interface abstracts the data source. Regardless of whether the input is a file, a string, an HTTP request, or a gRPC request, the implementation can be reused and easily tested.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/46-function-input/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/46-function-input/">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="ignoring-how-defer-arguments-and-receivers-are-evaluated-argument-evaluation-pointer-and-value-receivers-47">Ignoring how <code>defer</code> arguments and receivers are evaluated (argument evaluation, pointer, and value receivers) (#47)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3451,7 +3447,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span></code></pre></div>
|
||||
<p>Here, we wrap the calls to both <code>notify</code> and <code>incrementCounter</code> within a closure. This closure references the status variable from outside its body. Therefore, <code>status</code> is evaluated once the closure is executed, not when we call <code>defer</code>. This solution also works and doesn’t require <code>notify</code> and <code>incrementCounter</code> to change their signature.</p>
|
||||
<p>Let's also note this behavior applies with method receiver: the receiver is evaluated immediately.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/47-defer-evaluation/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/06-functions-methods/47-defer-evaluation/">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>
|
||||
<h2 id="error-management">Error Management</h2>
|
||||
<h3 id="panicking-48">Panicking (#48)</h3>
|
||||
<details class="info" open="open">
|
||||
|
|
@ -3474,7 +3470,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span><span id="__span-31-6"><a id="__codelineno-31-6" name="__codelineno-31-6" href="#__codelineno-31-6"></a> main.go:7 +0xb3
|
||||
</span></code></pre></div>
|
||||
<p>Panicking in Go should be used sparingly. There are two prominent cases, one to signal a programmer error (e.g., <a href="https://cs.opensource.google/go/go/+/refs/tags/go1.20.7:src/database/sql/sql.go;l=44"><code>sql.Register</code></a> that panics if the driver is <code>nil</code> or has already been register) and another where our application fails to create a mandatory dependency. Hence, exceptional conditions that lead us to stop the application. In most other cases, error management should be done with a function that returns a proper error type as the last return argument.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/48-panic/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/48-panic/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="ignoring-when-to-wrap-an-error-49">Ignoring when to wrap an error (#49)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3486,7 +3482,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<li>Marking an error as a specific error</li>
|
||||
</ul>
|
||||
<p>When handling an error, we can decide to wrap it. Wrapping is about adding additional context to an error and/or marking an error as a specific type. If we need to mark an error, we should create a custom error type. However, if we just want to add extra context, we should use fmt.Errorf with the %w directive as it doesn’t require creating a new error type. Yet, error wrapping creates potential coupling as it makes the source error available for the caller. If we want to prevent it, we shouldn’t use error wrapping but error transformation, for example, using fmt.Errorf with the %v directive.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/49-error-wrapping/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/49-error-wrapping/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="comparing-an-error-type-inaccurately-50">Comparing an error type inaccurately (#50)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3494,7 +3490,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</details>
|
||||
<!-- TODO -->
|
||||
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/50-compare-error-type/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/50-compare-error-type/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="comparing-an-error-value-inaccurately-51">Comparing an error value inaccurately (#51)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3511,7 +3507,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<li>Unexpected errors should be designed as error types: <code>type BarError struct { ... }</code>, with <code>BarError</code> implementing the <code>error</code> interface.</li>
|
||||
</ul>
|
||||
<p>If we use error wrapping in our application with the <code>%w</code> directive and <code>fmt.Errorf</code>, checking an error against a specific value should be done using <code>errors.Is</code> instead of <code>==</code>. Thus, even if the sentinel error is wrapped, <code>errors.Is</code> can recursively unwrap it and compare each error in the chain against the provided value.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/51-comparing-error-value/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/51-comparing-error-value/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="handling-an-error-twice-52">Handling an error twice (#52)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3519,13 +3515,13 @@ One additional note: we must remember that the standard library has some existin
|
|||
</details>
|
||||
<p>Handling an error multiple times is a mistake made frequently by developers, not specifically in Go. This can cause situations where the same error is logged multiple times make debugging harder.</p>
|
||||
<p>Let's remind us that handling an error should be done only once. Logging an error is handling an error. Hence, we should either log or return an error. By doing this, we simplify our code and gain better insights into the error situation. Using error wrapping is the most convenient approach as it allows us to propagate the source error and add context to an error.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/52-handling-error-twice/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/52-handling-error-twice/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="not-handling-an-error-53">Not handling an error (#53)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Ignoring an error, whether during a function call or in a <code>defer</code> function, should be done explicitly using the blank identifier. Otherwise, future readers may be confused about whether it was intentional or a miss.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/53-not-handling-error/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/53-not-handling-error/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="not-handling-defer-errors-54">Not handling <code>defer</code> errors (#54)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3550,7 +3546,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</span><span id="__span-35-2"><a id="__codelineno-35-2" name="__codelineno-35-2" href="#__codelineno-35-2"></a><span class="c1">// Hence, it's accepted to miss some of them in case of errors.</span>
|
||||
</span><span id="__span-35-3"><a id="__codelineno-35-3" name="__codelineno-35-3" href="#__codelineno-35-3"></a><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">notify</span><span class="p">()</span>
|
||||
</span></code></pre></div>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/54-defer-errors/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/07-error-management/54-defer-errors/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>
|
||||
<h2 id="concurrency-foundations">Concurrency: Foundations</h2>
|
||||
<h3 id="mixing-up-concurrency-and-parallelism-55">Mixing up concurrency and parallelism (#55)</h3>
|
||||
<details class="info" open="open">
|
||||
|
|
@ -3562,7 +3558,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<summary>TL;DR</summary>
|
||||
<p>To be a proficient developer, you must acknowledge that concurrency isn’t always faster. Solutions involving parallelization of minimal workloads may not necessarily be faster than a sequential implementation. Benchmarking sequential versus concurrent solutions should be the way to validate assumptions.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/56-faster/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/56-faster/">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="being-puzzled-about-when-to-use-channels-or-mutexes-57">Being puzzled about when to use channels or mutexes (#57)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3574,44 +3570,44 @@ One additional note: we must remember that the standard library has some existin
|
|||
<p>Being proficient in concurrency also means understanding that data races and race conditions are different concepts. Data races occur when multiple goroutines simultaneously access the same memory location and at least one of them is writing. Meanwhile, being data-race-free doesn’t necessarily mean deterministic execution. When a behavior depends on the sequence or the timing of events that can’t be controlled, this is a race condition.</p>
|
||||
</details>
|
||||
<p>Understanding the Go memory model and the underlying guarantees in terms of ordering and synchronization is essential to prevent possible data races and/or race conditions.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/58-races/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/58-races/">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="not-understanding-the-concurrency-impacts-of-a-workload-type-59">Not understanding the concurrency impacts of a workload type (#59)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>When creating a certain number of goroutines, consider the workload type. Creating CPU-bound goroutines means bounding this number close to the <code>GOMAXPROCS</code> variable (based by default on the number of CPU cores on the host). Creating I/O-bound goroutines depends on other factors, such as the external system.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/59-workload-type/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/59-workload-type/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="misunderstanding-go-contexts-60">Misunderstanding Go contexts (#60)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Go contexts are also one of the cornerstones of concurrency in Go. A context allows you to carry a deadline, a cancellation signal, and/or a list of keys-values.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/60-contexts/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/08-concurrency-foundations/60-contexts/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>
|
||||
<h2 id="concurrency-practice">Concurrency: Practice</h2>
|
||||
<h3 id="propagating-an-inappropriate-context-61">Propagating an inappropriate context (#61)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Understanding the conditions when a context can be canceled should matter when propagating it: for example, an HTTP handler canceling the context when the response has been sent.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/61-inappropriate-context/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/61-inappropriate-context/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="starting-a-goroutine-without-knowing-when-to-stop-it-62">Starting a goroutine without knowing when to stop it (#62)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Avoiding leaks means being mindful that whenever a goroutine is started, you should have a plan to stop it eventually.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/62-starting-goroutine/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/62-starting-goroutine/">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="not-being-careful-with-goroutines-and-loop-variables-63">Not being careful with goroutines and loop variables (#63)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>To avoid bugs with goroutines and loop variables, create local variables or call functions instead of closures.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/63-goroutines-loop-variables/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/63-goroutines-loop-variables/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="expecting-a-deterministic-behavior-using-select-and-channels-64">Expecting a deterministic behavior using select and channels (#64)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Understanding that <code>select</code> with multiple channels chooses the case randomly if multiple options are possible prevents making wrong assumptions that can lead to subtle concurrency bugs.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/64-select-behavior/main.go">Source code</a></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>
|
||||
<h3 id="not-using-notification-channels-65">Not using notification channels (#65)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3622,7 +3618,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<summary>TL;DR</summary>
|
||||
<p>Using nil channels should be part of your concurrency toolset because it allows you to <em>remove</em> cases from <code>select</code> statements, for example.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/66-nil-channels/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/66-nil-channels/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="being-puzzled-about-channel-size-67">Being puzzled about channel size (#67)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3634,78 +3630,78 @@ One additional note: we must remember that the standard library has some existin
|
|||
<summary>TL;DR</summary>
|
||||
<p>Being aware that string formatting may lead to calling existing functions means watching out for possible deadlocks and other data races.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/68-string-formatting/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/68-string-formatting/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="creating-data-races-with-append-69">Creating data races with append (#69)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Calling <code>append</code> isn’t always data-race-free; hence, it shouldn’t be used concurrently on a shared slice.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/69-data-race-append/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/69-data-race-append/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-mutexes-inaccurately-with-slices-and-maps-70">Using mutexes inaccurately with slices and maps (#70)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Remembering that slices and maps are pointers can prevent common data races.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/70-mutex-slices-maps/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/70-mutex-slices-maps/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="misusing-syncwaitgroup-71">Misusing <code>sync.WaitGroup</code> (#71)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>To accurately use <code>sync.WaitGroup</code>, call the <code>Add</code> method before spinning up goroutines.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/71-wait-group/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/71-wait-group/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="forgetting-about-synccond-72">Forgetting about <code>sync.Cond</code> (#72)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>You can send repeated notifications to multiple goroutines with <code>sync.Cond</code>.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/72-cond/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/72-cond/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="not-using-errgroup-73">Not using <code>errgroup</code> (#73)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>You can synchronize a group of goroutines and handle errors and contexts with the <code>errgroup</code> package.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/73-errgroup/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/73-errgroup/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="copying-a-sync-type-74">Copying a <code>sync</code> type (#74)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p><code>sync</code> types shouldn’t be copied.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/74-copying-sync/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/74-copying-sync/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>
|
||||
<h2 id="standard-library">Standard Library</h2>
|
||||
<h3 id="providing-a-wrong-time-duration-75">Providing a wrong time duration (#75)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Remain cautious with functions accepting a <code>time.Duration</code>. Even though passing an integer is allowed, strive to use the time API to prevent any possible confusion.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/75-wrong-time-duration/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/75-wrong-time-duration/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="timeafter-and-memory-leaks-76"><code>time.After</code> and memory leaks (#76)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Avoiding calls to <code>time.After</code> in repeated functions (such as loops or HTTP handlers) can avoid peak memory consumption. The resources created by <code>time.After</code> are released only when the timer expires.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/76-time-after/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/76-time-after/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="json-handling-common-mistakes-77">JSON handling common mistakes (#77)</h3>
|
||||
<ul>
|
||||
<li>Unexpected behavior because of type embedding</li>
|
||||
</ul>
|
||||
<p>Be careful about using embedded fields in Go structs. Doing so may lead to sneaky bugs like an embedded time.Time field implementing the <code>json.Marshaler</code> interface, hence overriding the default marshaling behavior.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/type-embedding/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/type-embedding/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>
|
||||
<ul>
|
||||
<li>JSON and the monotonic clock</li>
|
||||
</ul>
|
||||
<p>When comparing two <code>time.Time</code> structs, recall that <code>time.Time</code> contains both a wall clock and a monotonic clock, and the comparison using the == operator is done on both clocks.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/monotonic-clock/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/monotonic-clock/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>
|
||||
<ul>
|
||||
<li>Map of <code>any</code></li>
|
||||
</ul>
|
||||
<p>To avoid wrong assumptions when you provide a map while unmarshaling JSON data, remember that numerics are converted to <code>float64</code> by default.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/map-any/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/77-json-handling/map-any/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="common-sql-mistakes-78">Common SQL mistakes (#78)</h3>
|
||||
<ul>
|
||||
<li>Forgetting that <code>sql.Open</code> doesn't necessarily establish connections to a database</li>
|
||||
</ul>
|
||||
<p>Call the <code>Ping</code> or <code>PingContext</code> method if you need to test your configuration and make sure a database is reachable.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/sql-open">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/sql-open">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>
|
||||
<ul>
|
||||
<li>Forgetting about connections pooling</li>
|
||||
</ul>
|
||||
|
|
@ -3714,42 +3710,42 @@ One additional note: we must remember that the standard library has some existin
|
|||
<li>Not using prepared statements</li>
|
||||
</ul>
|
||||
<p>Using SQL prepared statements makes queries more efficient and more secure.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/prepared-statements">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/prepared-statements">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>
|
||||
<ul>
|
||||
<li>Mishandling null values</li>
|
||||
</ul>
|
||||
<p>Deal with nullable columns in tables using pointers or <code>sql.NullXXX</code> types.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/null-values/main.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/null-values/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>
|
||||
<ul>
|
||||
<li>Not handling rows iteration errors</li>
|
||||
</ul>
|
||||
<p>Call the <code>Err</code> method of <code>sql.Rows</code> after row iterations to ensure that you haven’t missed an error while preparing the next row.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/rows-iterations-errors">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/78-sql/rows-iterations-errors">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="not-closing-transient-resources-http-body-sqlrows-and-osfile-79">Not closing transient resources (HTTP body, <code>sql.Rows</code>, and <code>os.File</code>) (#79)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Eventually close all structs implementing <code>io.Closer</code> to avoid possible leaks.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/79-closing-resources/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/79-closing-resources/">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="forgetting-the-return-statement-after-replying-to-an-http-request-80">Forgetting the return statement after replying to an HTTP request (#80)</h3>
|
||||
<details class="info" open="open">
|
||||
<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><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/80-http-return/main.go">Source code</a></p>
|
||||
<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">
|
||||
<summary>TL;DR</summary>
|
||||
<p>For production-grade applications, don’t use the default HTTP client and server implementations. These implementations are missing timeouts and behaviors that should be mandatory in production.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/81-default-http-client-server/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/10-standard-lib/81-default-http-client-server/">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>
|
||||
<h2 id="testing">Testing</h2>
|
||||
<h3 id="not-categorizing-tests-build-tags-environment-variables-and-short-mode-82">Not categorizing tests (build tags, environment variables, and short mode) (#82)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Categorizing tests using build flags, environment variables, or short mode makes the testing process more efficient. You can create test categories using build flags or environment variables (for example, unit versus integration tests) and differentiate short from long-running tests to decide which kinds of tests to execute.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/82-categorizing-tests/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/82-categorizing-tests/">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="not-enabling-the-race-flag-83">Not enabling the race flag (#83)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3765,28 +3761,28 @@ One additional note: we must remember that the standard library has some existin
|
|||
<summary>TL;DR</summary>
|
||||
<p>Table-driven tests are an efficient way to group a set of similar tests to prevent code duplication and make future updates easier to handle.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/85-table-driven-tests/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/85-table-driven-tests/main_test.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="sleeping-in-unit-tests-86">Sleeping in unit tests (#86)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Avoid sleeps using synchronization to make a test less flaky and more robust. If synchronization isn’t possible, consider a retry approach.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/86-sleeping/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/86-sleeping/main_test.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="not-dealing-with-the-time-api-efficiently-87">Not dealing with the time API efficiently (#87)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Understanding how to deal with functions using the time API is another way to make a test less flaky. You can use standard techniques such as handling the time as part of a hidden dependency or asking clients to provide it.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/87-time-api/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/87-time-api/">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="not-using-testing-utility-packages-httptest-and-iotest-88">Not using testing utility packages (<code>httptest</code> and <code>iotest</code>) (#88)</h3>
|
||||
<ul>
|
||||
<li>The <code>httptest</code> package is helpful for dealing with HTTP applications. It provides a set of utilities to test both clients and servers.</li>
|
||||
</ul>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/httptest/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/httptest/main_test.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>
|
||||
<ul>
|
||||
<li>The <code>iotest</code> package helps write io.Reader and test that an application is tolerant to errors.</li>
|
||||
</ul>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/iotest/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/88-utility-package/iotest/main_test.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="writing-inaccurate-benchmarks-89">Writing inaccurate benchmarks (#89)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3800,7 +3796,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
</ul>
|
||||
</details>
|
||||
<p>Read the full section <a href="89-benchmarks/">here</a>.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/89-benchmark/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/89-benchmark/">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="not-exploring-all-the-go-testing-features-90">Not exploring all the Go testing features (#90)</h3>
|
||||
<ul>
|
||||
<li>Code coverage</li>
|
||||
|
|
@ -3810,17 +3806,17 @@ One additional note: we must remember that the standard library has some existin
|
|||
<li>Testing from a different package</li>
|
||||
</ul>
|
||||
<p>Place unit tests in a different package to enforce writing tests that focus on an exposed behavior, not internals.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/different-package/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/different-package/main_test.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>
|
||||
<ul>
|
||||
<li>Utility functions</li>
|
||||
</ul>
|
||||
<p>Handling errors using the <code>*testing.T</code> variable instead of the classic <code>if err != nil</code> makes code shorter and easier to read.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/utility-function/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/utility-function/main_test.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>
|
||||
<ul>
|
||||
<li>Setup and teardown</li>
|
||||
</ul>
|
||||
<p>You can use setup and teardown functions to configure a complex environment, such as in the case of integration tests.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/setup-teardown/main_test.go">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/11-testing/90-testing-features/setup-teardown/main_test.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="not-using-fuzzing-community-mistake">Not using fuzzing (community mistake)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
@ -3837,18 +3833,18 @@ One additional note: we must remember that the standard library has some existin
|
|||
<li>Cache line</li>
|
||||
</ul>
|
||||
<p>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.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/cache-line/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/cache-line/">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>
|
||||
<ul>
|
||||
<li>Slice of structs vs. struct of slices</li>
|
||||
</ul>
|
||||
<!-- TODO -->
|
||||
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/slice-structs/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/slice-structs/">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>
|
||||
<ul>
|
||||
<li>Predictability</li>
|
||||
</ul>
|
||||
<p>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.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/predictability/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/91-cpu-caches/predictability/">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>
|
||||
<ul>
|
||||
<li>Cache placement policy</li>
|
||||
</ul>
|
||||
|
|
@ -3858,31 +3854,31 @@ One additional note: we must remember that the standard library has some existin
|
|||
<summary>TL;DR</summary>
|
||||
<p>Knowing that lower levels of CPU caches aren’t shared across all the cores helps avoid performance-degrading patterns such as false sharing while writing concurrency code. Sharing memory is an illusion.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/92-false-sharing/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/92-false-sharing/">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="not-taking-into-account-instruction-level-parallelism-93">Not taking into account instruction-level parallelism (#93)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Use instruction-level parallelism (ILP) to optimize specific parts of your code to allow a CPU to execute as many parallel instructions as possible. Identifying data hazards is one of the main steps.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/93-instruction-level-parallelism/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/93-instruction-level-parallelism/">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="not-being-aware-of-data-alignment-94">Not being aware of data alignment (#94)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>You can avoid common mistakes by remembering that in Go, basic types are aligned with their own size. For example, keep in mind that reorganizing the fields of a struct by size in descending order can lead to more compact structs (less memory allocation and potentially a better spatial locality).</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/94-data-alignment/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/94-data-alignment/">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="not-understanding-stack-vs-heap-95">Not understanding stack vs. heap (#95)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Understanding the fundamental differences between heap and stack should also be part of your core knowledge when optimizing a Go application. Stack allocations are almost free, whereas heap allocations are slower and rely on the GC to clean the memory.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/95-stack-heap/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/95-stack-heap/">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="not-knowing-how-to-reduce-allocations-api-change-compiler-optimizations-and-syncpool-96">Not knowing how to reduce allocations (API change, compiler optimizations, and <code>sync.Pool</code>) (#96)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Reducing allocations is also an essential aspect of optimizing a Go application. This can be done in different ways, such as designing the API carefully to prevent sharing up, understanding the common Go compiler optimizations, and using <code>sync.Pool</code>.</p>
|
||||
</details>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/96-reduce-allocations/">Source code</a></p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/12-optimizations/96-reduce-allocations/">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="not-relying-on-inlining-97">Not relying on inlining (#97)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
|
@ -1,3 +1,15 @@
|
|||
.md-typeset figure img {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.md-tabs__link {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.md-tabs__link:hover {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.md-tabs__link:focus {
|
||||
color: blue;
|
||||
}
|
||||
Loading…
Reference in a new issue