Structure

This commit is contained in:
Teiva Harsanyi 2023-09-12 17:56:50 +02:00
parent 3dc5a022f9
commit 6e611d8556
19 changed files with 2568 additions and 634 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -1,8 +1,4 @@
---
title: Book Presentation
---
# Book Presentation
# Presentation
Source code and community space of _100 Go Mistakes and How to Avoid Them_, published by Manning in 2022.

View file

@ -5,13 +5,16 @@ title: Read the First Chapter
# Go: Simple to learn but hard to master
This chapter covers
* What makes Go an efficient, scalable, and productive language
* Exploring why Go is simple to learn but hard to master
* Presenting the common types of mistakes made by developers
Making mistakes is part of everyones life. As Albert Einstein once said,
> A person who never made a mistake never tried anything new.
!!! quote "Albert Einstein"
A person who never made a mistake never tried anything new.
What matters in the end isnt the number of mistakes we make, but our capacity to learn from them. This assertion also applies to programming. The seniority we acquire in a language isnt a magical process; it involves making many mistakes and learning from them. The purpose of this book is centered around this idea. It will help you, the reader, become a more proficient Go developer by looking at and learning from 100 common mistakes people make in many areas of the language.
@ -27,7 +30,9 @@ In response to these challenges, Google created the Go programming language in 2
Feature-wise, Go has no type inheritance, no exceptions, no macros, no partial functions, no support for lazy variable evaluation or immutability, no operator overloading, no pattern matching, and on and on. Why are these features missing from the language? The official [Go FAQ](https://go.dev/doc/faq) gives us some insight:
> Why does Go not have feature X? Your favorite feature may be missing because it doesnt fit, because it affects compilation speed or clarity of design, or because it would make the fundamental system model too difficult.
!!! quote "Go FAQ"
Why does Go not have feature X? Your favorite feature may be missing because it doesnt fit, because it affects compilation speed or clarity of design, or because it would make the fundamental system model too difficult.
Judging the quality of a programming language via its number of features is probably not an accurate metric. At least, its not an objective of Go. Instead, Go utilizes a few essential characteristics when adopting a language at scale for an organization. These include the following:
@ -62,9 +67,9 @@ In a 2011 article, neuroscientists proved that the best time for brain growth is
To strengthen this facilitative effect, this book accompanies each mistake as much as possible with real-world examples. This book isnt only about theory; it also helps us get better at avoiding mistakes and making more well-informed, conscious decisions because we now understand the rationale behind them.
> Tell me and I forget. Teach me and I remember. Involve me and I learn.
!!! quote "Unknown"
_- Unknown_
Tell me and I forget. Teach me and I remember. Involve me and I learn.
This book presents seven main categories of mistakes. Overall, the mistakes can be classified as

View file

@ -1,8 +1,16 @@
# 💡 Common Go Mistakes
---
title: English
---
# Common Go Mistakes
This section contains a summary of the 100 mistakes in the book. Meanwhile, it's also a section open to the community. If you believe that a mistake should be added, please create a [community mistake issue](https://github.com/teivah/100-go-mistakes/issues/new?assignees=&labels=community+mistake&template=community_mistake.md&title=).
**Note:** 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.
If you want to engage with the community (asking questions, discussing options, etc.), feel free to use the [Discussions](https://github.com/teivah/100-go-mistakes/discussions) space on the GitHub repo.
???+ info
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 -->
@ -14,7 +22,9 @@ This section contains a summary of the 100 mistakes in the book. Meanwhile, it's
### Unintended variable shadowing (#1)
**TL;DR**: Avoiding shadowed variables can help prevent mistakes like referencing the wrong variable or confusing readers.
???+ info "TL;DR"
Avoiding shadowed variables can help prevent mistakes like referencing the wrong variable or confusing readers.
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.
@ -22,7 +32,9 @@ Variable shadowing occurs when a variable name is redeclared in an inner block,
### Unnecessary nested code (#2)
**TL;DR**: Avoiding nested levels and keeping the happy path aligned on the left makes building a mental code model easier.
???+ info "TL;DR"
Avoiding nested levels and keeping the happy path aligned on the left makes building a mental code model easier.
In general, the more nested levels a function requires, the more complex it is to read and understand. Lets see some different applications of this rule to optimize our code for readability:
@ -37,7 +49,7 @@ if foo() {
}
```
Instead, we omit the `else` block like this:
Instead, we omit the `else` block like this:
```go
if foo() {
@ -73,7 +85,9 @@ Writing readable code is an important challenge for every developer. Striving to
### Misusing init functions (#3)
**TL;DR**: When initializing variables, remember that init functions have limited error handling and make state handling and testing more complex. In most cases, initializations should be handled as specific functions.
???+ info "TL;DR"
When initializing variables, remember that init functions have limited error handling and make state handling and testing more complex. In most cases, initializations should be handled as specific functions.
An init function is a function used to initialize the state of an application. It takes no arguments and returns no result (a `func()` function). When a package is initialized, all the constant and variable declarations in the package are evaluated. Then, the init functions are executed.
@ -88,7 +102,9 @@ We should be cautious with init functions. They can be helpful in some situation
### Overusing getters and setters (#4)
**TL;DR**: Forcing the use of getters and setters isnt idiomatic in Go. Being pragmatic and finding the right balance between efficiency and blindly following certain idioms should be the way to go.
???+ info "TL;DR"
Forcing the use of getters and setters isnt idiomatic in Go. Being pragmatic and finding the right balance between efficiency and blindly following certain idioms should be the way to go.
Data encapsulation refers to hiding the values or state of an object. Getters and setters are means to enable encapsulation by providing exported methods on top of unexported object fields.
@ -98,7 +114,9 @@ Remember that Go is a unique language designed for many characteristics, includi
### Interface pollution (#5)
**TL;DR**: Abstractions should be discovered, not created. To prevent unnecessary complexity, create an interface when you need it and not when you foresee needing it, or if you can at least prove the abstraction to be a valid one.
???+ info "TL;DR"
Abstractions should be discovered, not created. To prevent unnecessary complexity, create an interface when you need it and not when you foresee needing it, or if you can at least prove the abstraction to be a valid one.
An interface provides a way to specify the behavior of an object. We use interfaces to create common abstractions that multiple objects can implement. What makes Go interfaces so different is that they are satisfied implicitly. There is no explicit keyword like `implements` to mark that an object `X` implements interface `Y`.
@ -109,9 +127,9 @@ Whats the main problem if we overuse interfaces? The answer is that they make
We should be cautious when creating abstractions in our code (abstractions should be discovered, not created). Its common for us, software developers, to overengineer our code by trying to guess what the perfect level of abstraction is, based on what we think we might need later. This process should be avoided because, in most cases, it pollutes our code with unnecessary abstractions, making it more complex to read.
> Dont design with interfaces, discover them.
!!! quote "Rob Pike"
_Rob Pike_
Dont design with interfaces, discover them.
Lets not try to solve a problem abstractly but solve what has to be solved now. Last, but not least, if its unclear how an interface makes the code better, we should probably consider removing it to make our code simpler.
@ -119,7 +137,9 @@ Lets not try to solve a problem abstractly but solve what has to be solved no
### Interface on the producer side (#6)
**TL;DR**: Keeping interfaces on the client side avoids unnecessary abstractions.
???+ info "TL;DR"
Keeping interfaces on the client side avoids unnecessary abstractions.
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: _abstractions should be discovered, not created_. This means that its not up to the producer to force a given abstraction for all the clients. Instead, its up to the client to decide whether it needs some form of abstraction and then determine the best abstraction level for its needs.
@ -129,13 +149,17 @@ An interface should live on the consumer side in most cases. However, in particu
### Returning interfaces (#7)
**TL;DR**: To prevent being restricted in terms of flexibility, a function shouldnt return interfaces but concrete implementations in most cases. Conversely, a function should accept interfaces whenever possible.
???+ info "TL;DR"
To prevent being restricted in terms of flexibility, a function shouldnt return interfaces but concrete implementations in most cases. Conversely, a function should accept interfaces whenever possible.
In most cases, we shouldnt return interfaces but concrete implementations. Otherwise, it can make our design more complex due to package dependencies and can restrict flexibility because all the clients would have to rely on the same abstraction. Again, the conclusion is similar to the previous sections: if we know (not foresee) that an abstraction will be helpful for clients, we can consider returning an interface. Otherwise, we shouldnt force abstractions; they should be discovered by clients. If a client needs to abstract an implementation for whatever reason, it can still do that on the clients side.
### `any` says nothing (#8)
**TL;DR**: Only use `any` if you need to accept or return any possible type, such as `json.Marshal`. Otherwise, `any` doesnt provide meaningful information and can lead to compile-time issues by allowing a caller to call methods with any data type.
???+ info "TL;DR"
Only use `any` if you need to accept or return any possible type, such as `json.Marshal`. Otherwise, `any` doesnt provide meaningful information and can lead to compile-time issues by allowing a caller to call methods with any data type.
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.
@ -143,7 +167,9 @@ The `any` type can be helpful if there is a genuine need for accepting or return
### Being confused about when to use generics (#9)
**TL;DR**: 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.
???+ info "TL;DR"
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.
<!-- TODO Include 9-generics.md file -->
@ -151,7 +177,9 @@ The `any` type can be helpful if there is a genuine need for accepting or return
### Not being aware of the possible problems with type embedding (#10)
**TL;DR**: Using type embedding can also help avoid boilerplate code; however, ensure that doing so doesnt lead to visibility issues where some fields should have remained hidden.
???+ info "TL;DR"
Using type embedding can also help avoid boilerplate code; however, ensure that doing so doesnt lead to visibility issues where some fields should have remained hidden.
When creating a struct, Go offers the option to embed types. But this can sometimes lead to unexpected behaviors if we dont understand all the implications of type embedding. Throughout this section, we look at how to embed types, what these bring, and the possible issues.
@ -184,7 +212,9 @@ Using type embedding consciously by keeping these constraints in mind can help a
### Not using the functional options pattern (#11)
**TL;DR**: To handle options conveniently and in an API-friendly manner, use the functional options pattern.
???+ info "TL;DR"
To handle options conveniently and in an API-friendly manner, use the functional options pattern.
Although there are different implementations with minor variations, the main idea is as follows:
* An unexported struct holds the configuration: options.
@ -241,7 +271,9 @@ The functional options pattern provides a handy and API-friendly way to handle o
### Project misorganization (project structure and package organization) (#12)
**TL;DR**: Following a layout such as [project-layout](https://github.com/golang-standards/project-layout) can be a good way to start structuring Go projects, especially if you are looking for existing conventions to standardize a new project.
???+ info "TL;DR"
Following a layout such as [project-layout](https://github.com/golang-standards/project-layout) can be a good way to start structuring Go projects, especially if you are looking for existing conventions to standardize a new project.
Regarding the overall organization, there are different schools of thought. For example, should we organize our application by context or by layer? It depends on our preferences. We may favor grouping code per context (such as the customer context, the contract context, etc.), or we may favor following hexagonal architecture principles and group per technical layer. If the decision we make fits our use case, it cannot be a wrong decision, as long as we remain consistent with it.
@ -256,7 +288,9 @@ Organizing a project isnt straightforward, but following these rules should h
### Creating utility packages (#13)
**TL;DR**: Naming is a critical piece of application design. Creating packages such as `common`, `util`, and `shared` doesnt bring much value for the reader. Refactor such packages into meaningful and specific package names.
???+ info "TL;DR"
Naming is a critical piece of application design. Creating packages such as `common`, `util`, and `shared` doesnt bring much value for the reader. Refactor such packages into meaningful and specific package names.
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.
@ -264,13 +298,17 @@ Also, bear in mind that naming a package after what it provides and not what it
### Ignoring package name collisions (#14)
**TL;DR**: To avoid naming collisions between variables and packages, leading to confusion or perhaps even bugs, use unique names for each one. If this isnt feasible, use an import alias to change the qualifier to differentiate the package name from the variable name, or think of a better name.
???+ info "TL;DR"
To avoid naming collisions between variables and packages, leading to confusion or perhaps even bugs, use unique names for each one. If this isnt feasible, use an import alias to change the qualifier to differentiate the package name from the variable name, or think of a better name.
Package collisions occur when a variable name collides with an existing package name, preventing the package from being reused. We should prevent variable name collisions to avoid ambiguity. If we face a collision, we should either find another meaningful name or use an import alias.
### Missing code documentation (#15)
**TL;DR**: To help clients and maintainers understand your codes purpose, document exported elements.
???+ info "TL;DR"
To help clients and maintainers understand your codes purpose, document exported elements.
Documentation is an important aspect of coding. It simplifies how clients can consume an API but can also help in maintaining a project. In Go, we should follow some rules to make our code idiomatic:
@ -286,7 +324,9 @@ Documenting our code shouldnt be a constraint. We should take the opportunity
### Not using linters (#16)
**TL;DR**: To improve code quality and consistency, use linters and formatters.
???+ info "TL;DR"
To improve code quality and consistency, use linters and formatters.
A linter is an automatic tool to analyze code and catch errors. The scope of this section isnt to give an exhaustive list of the existing linters; otherwise, it will become deprecated pretty quickly. But we should understand and remember why linters are essential for most Go projects.
@ -308,7 +348,9 @@ Linters and formatters are a powerful way to improve the quality and consistency
### Creating confusion with octal literals (#17)
**TL;DR**: When reading existing code, bear in mind that integer literals starting with 0 are octal numbers. Also, to improve readability, make octal integers explicit by prefixing them with `0o`.
???+ info "TL;DR"
When reading existing code, bear in mind that integer literals starting with 0 are octal numbers. Also, to improve readability, make octal integers explicit by prefixing them with `0o`.
Octal numbers start with a 0 (e.g., `010` is equal to 8 in base 10). To improve readability and avoid potential mistakes for future code readers, we should make octal numbers explicit using the `0o` prefix (e.g., `0o10`).
@ -323,7 +365,9 @@ We can also use an underscore character (_) as a separator for readability. For
### Neglecting integer overflows (#18)
**TL;DR**: Because integer overflows and underflows are handled silently in Go, you can implement your own functions to catch them.
???+ info "TL;DR"
Because integer overflows and underflows are handled silently in Go, you can implement your own functions to catch them.
In Go, an integer overflow that can be detected at compile time generates a compila- tion error. For example,
@ -341,7 +385,9 @@ However, at run time, an integer overflow or underflow is silent; this does not
### Not understanding floating-points (#19)
**TL;DR**: Making floating-point comparisons within a given delta can ensure that your code is portable. When performing addition or subtraction, group the operations with a similar order of magnitude to favor accuracy. Also, perform multiplication and division before addition and subtraction.
???+ info "TL;DR"
Making floating-point comparisons within a given delta can ensure that your code is portable. When performing addition or subtraction, group the operations with a similar order of magnitude to favor accuracy. Also, perform multiplication and division before addition and subtraction.
In Go, there are two floating-point types (if we omit imaginary numbers): float32 and float64. The concept of a floating point was invented to solve the major problem with integers: their inability to represent fractional values. To avoid bad surprises, we need to know that floating-point arithmetic is an approximation of real arithmetic.
@ -363,7 +409,9 @@ Because Gos `float32` and `float64` types are approximations, we have to bear
### Not understanding slice length and capacity (#20)
**TL;DR**: Understanding the difference between slice length and capacity should be part of a Go developers 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.
???+ info "TL;DR"
Understanding the difference between slice length and capacity should be part of a Go developers 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.
<!-- TODO -->
@ -371,7 +419,9 @@ Because Gos `float32` and `float64` types are approximations, we have to bear
### Inefficient slice initialization (#21)
**TL;DR**: When creating a slice, initialize it with a given length or capacity if its length is already known. This reduces the number of allocations and improves performance.
???+ info "TL;DR"
When creating a slice, initialize it with a given length or capacity if its length is already known. This reduces the number of allocations and improves performance.
While initializing a slice using `make`, 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, theres no good reason not to give the Go runtime a helping hand.
@ -381,7 +431,9 @@ Our options are to allocate a slice with either a given capacity or a given leng
### Being confused about nil vs. empty slice (#22)
**TL;DR**: To prevent common confusions such as when using the `encoding/json` or the `reflect` package, you need to understand the difference between nil and empty slices. Both are zero-length, zero-capacity slices, but only a nil slice doesnt require allocation.
???+ info "TL;DR"
To prevent common confusions such as when using the `encoding/json` or the `reflect` package, you need to understand the difference between nil and empty slices. Both are zero-length, zero-capacity slices, but only a nil slice doesnt require allocation.
In Go, there is a distinction between nil and empty slices. A nil slice is equals to `nil`, whereas an empty slice has a length of zero. A nil slice is empty, but an empty slice isnt necessarily `nil`. Meanwhile, a nil slice doesnt require any allocation. We have seen throughout this section how to initialize a slice depending on the con- text by using
@ -395,7 +447,9 @@ The last option, `[]string{}`, should be avoided if we initialize the slice with
### Not properly checking if a slice is empty (#23)
**TL;DR**: To check if a slice doesnt contain any element, check its length. This check works regardless of whether the slice is `nil` or empty. The same goes for maps. To design unambiguous APIs, you shouldnt distinguish between nil and empty slices.
???+ info "TL;DR"
To check if a slice doesnt contain any element, check its length. This check works regardless of whether the slice is `nil` or empty. The same goes for maps. To design unambiguous APIs, you shouldnt distinguish between nil and empty slices.
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.
@ -405,7 +459,9 @@ Meanwhile, when designing interfaces, we should avoid distinguishing nil and emp
### Not making slice copies correctly (#24)
**TL;DR**: To copy one slice to another using the `copy` built-in function, remember that the number of copied elements corresponds to the minimum between the two slices lengths.
???+ info "TL;DR"
To copy one slice to another using the `copy` built-in function, remember that the number of copied elements corresponds to the minimum between the two slices lengths.
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 destina- tion corresponds to the minimum between the two slices lengths. Also bear in mind that other alternatives exist to copy a slice, so we shouldnt be surprised if we find them in a codebase.
@ -413,18 +469,23 @@ Copying elements from one slice to another is a reasonably frequent operation. W
### Unexpected side effects using slice append (#25)
**TL;DR**: Using copy or the full slice expression is a way to prevent `append` from creating conflicts if two different functions use slices backed by the same array. However, only a slice copy prevents memory leaks if you want to shrink a large slice.
???+ info "TL;DR"
Using copy or the full slice expression is a way to prevent `append` from creating conflicts if two different functions use slices backed by the same array. However, only a slice copy prevents memory leaks if you want to shrink a large slice.
When using slicing, we must remember that we can face a situation leading to unintended side effects. If the resulting slice has a length smaller than its capacity, append can mutate the original slice. If we want to restrict the range of possible side effects, we can use either a slice copy or the full slice expression, which prevents us from doing a copy.
> [!NOTE]
> `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 slices capacity is equal to `max - low`.
???+ note
`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 slices 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)
### Slice and memory leaks (#26)
**TL;DR**: Working with a slice of pointers or structs with pointer fields, you can avoid memory leaks by marking as nil the elements excluded by a slicing operation.
???+ info "TL;DR"
Working with a slice of pointers or structs with pointer fields, you can avoid memory leaks by marking as nil the elements excluded by a slicing operation.
#### Leaking capacity
@ -440,7 +501,9 @@ When we use the slicing operation with pointers or structs with pointer fields,
### Inefficient map initialization (#27)
**TL;DR**: When creating a map, initialize it with a given length if its length is already known. This reduces the number of allocations and improves performance.
???+ info "TL;DR"
When creating a map, initialize it with a given length if its length is already known. This reduces the number of allocations and improves performance.
A map provides an unordered collection of key-value pairs in which all the keys are dis- tinct. 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.
@ -450,7 +513,9 @@ If we know up front the number of elements a map will contain, we should create
### [Map and memory leaks](https://teivah.medium.com/maps-and-memory-leaks-in-go-a85ebe6e7e69) (#28)
**TL;DR**: 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.
???+ info "TL;DR"
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.
<!-- TODO -->
@ -458,7 +523,9 @@ If we know up front the number of elements a map will contain, we should create
### Comparing values incorrectly (#29)
**TL;DR**: To compare types in Go, you can use the == and != operators if two types are comparable: Booleans, numerals, strings, pointers, channels, and structs are composed entirely of comparable types. Otherwise, you can either use `reflect.DeepEqual` and pay the price of reflection or use custom implementations and libraries.
???+ info "TL;DR"
To compare types in Go, you can use the == and != operators if two types are comparable: Booleans, numerals, strings, pointers, channels, and structs are composed entirely of comparable types. Otherwise, you can either use `reflect.DeepEqual` and pay the price of reflection or use custom implementations and libraries.
Its essential to understand how to use `==` and `!=` to make comparisons effectively. We can use these operators on operands that are comparable:
* _Booleans_—Compare whether two Booleans are equal.
@ -469,8 +536,9 @@ Its essential to understand how to use `==` and `!=` to make comparisons effe
* _Pointers_—Compare whether two pointers point to the same value in memory or if both are nil.
* _Structs and arrays)—Compare whether they are composed of similar types.
> [!NOTE]
> We can also use the `?`, `>=`, `<`, and `>` operators with numeric types to compare values and with strings to compare their lexical order.
???+ note
We can also use the `?`, `>=`, `<`, and `>` operators with numeric types to compare values and with strings to compare their lexical order.
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 applica- tion to introspect and modify its structure and behavior. For example, in Go, we can use `reflect.DeepEqual`. 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.
@ -484,7 +552,9 @@ One additional note: we must remember that the standard library has some exist-
### Ignoring that elements are copied in `range` loops (#30)
**TL;DR**: The value element in a `range` loop is a copy. Therefore, to mutate a struct, for example, access it via its index or via a classic `for` loop (unless the element or the field you want to modify is a pointer).
???+ info "TL;DR"
The value element in a `range` loop is a copy. Therefore, to mutate a struct, for example, access it via its index or via a classic `for` loop (unless the element or the field you want to modify is a pointer).
A range loop allows iterating over different data structures:
* String
@ -502,7 +572,9 @@ Yet, we should remember that the value element in a range loop is a copy. Theref
### Ignoring how arguments are evaluated in `range` loops (channels and arrays) (#31)
**TL;DR**: Understanding that the expression passed to the `range` operator is evaluated only once before the beginning of the loop can help you avoid common mistakes such as inefficient assignment in channel or slice iteration.
???+ info "TL;DR"
Understanding that the expression passed to the `range` operator is evaluated only once before the beginning of the loop can help you avoid common mistakes such as inefficient assignment in channel or slice iteration.
The range loop evaluates the provided expression only once, before the beginning of the loop, by doing a copy (regardless of the type). We should remember this behavior to avoid common mistakes that might, for example, lead us to access the wrong element. For example:
@ -522,7 +594,9 @@ This code updates the last index to 10. However, if we run this code, it does no
### Ignoring the impacts of using pointer elements in `range` loops (#32)
**TL;DR**: Using a local variable or accessing an element using an index, you can prevent mistakes while copying pointers inside a loop.
???+ info "TL;DR"
Using a local variable or accessing an element using an index, you can prevent mistakes while copying pointers inside a loop.
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 situ- ation 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 loops scope or creating a pointer referencing a slice element via its index. Both solutions are fine.
@ -530,7 +604,9 @@ When iterating over a data structure using a `range` loop, we must recall that a
### Making wrong assumptions during map iterations (ordering and map insert during iteration) (#33)
**TL;DR**: To ensure predictable outputs when using maps, remember that a map data structure:
???+ info "TL;DR"
To ensure predictable outputs when using maps, remember that a map data structure:
* Doesnt order the data by keys
* Doesnt preserve the insertion order
* Doesnt have a deterministic iteration order
@ -542,7 +618,9 @@ When iterating over a data structure using a `range` loop, we must recall that a
### Ignoring how the `break` statement works (#34)
**TL;DR**: Using `break` or `continue` with a label enforces breaking a specific statement. This can be helpful with `switch` or `select` statements inside loops.
???+ info "TL;DR"
Using `break` or `continue` with a label enforces breaking a specific statement. This can be helpful with `switch` or `select` statements inside loops.
A break statement is commonly used to terminate the execution of a loop. When loops are used in conjunction with switch or select, developers frequently make the mistake of breaking the wrong statement. For example:
@ -583,7 +661,9 @@ Here, we associate the `loop` label with the `for` loop. Then, because we provid
### Using `defer` inside a loop (#35)
**TL;DR**: Extracting loop logic inside a function leads to executing a `defer` statement at the end of each iteration.
???+ info "TL;DR"
Extracting loop logic inside a function leads to executing a `defer` statement at the end of each iteration.
The `defer` statement delays a calls execution until the surrounding function returns. Its mainly used to reduce boilerplate code. For example, if a resource has to be closed eventually, we can use `defer` to avoid repeating the closure calls before every single `return`.
@ -640,7 +720,9 @@ Another solution is to make the `readFile` function a closure but intrinsically,
### Not understanding the concept of rune (#36)
**TL;DR**: Understanding that a rune corresponds to the concept of a Unicode code point and that it can be composed of multiple bytes should be part of the Go developers core knowledge to work accurately with strings.
???+ info "TL;DR"
Understanding that a rune corresponds to the concept of a Unicode code point and that it can be composed of multiple bytes should be part of the Go developers core knowledge to work accurately with strings.
As runes are everywhere in Go, it's important to understand the following:
@ -655,7 +737,9 @@ As runes are everywhere in Go, it's important to understand the following:
### Inaccurate string iteration (#37)
**TL;DR**: Iterating on a string with the `range` operator iterates on the runes with the index corresponding to the starting index of the runes byte sequence. To access a specific rune index (such as the third rune), convert the string into a `[]rune`.
???+ info "TL;DR"
Iterating on a string with the `range` operator iterates on the runes with the index corresponding to the starting index of the runes byte sequence. To access a specific rune index (such as the third rune), convert the string into a `[]rune`.
Iterating on a string is a common operation for developers. Perhaps we want to per- form an operation for each rune in the string or implement a custom function to search for a specific substring. In both cases, we have to iterate on the different runes of a string. But its easy to get confused about how iteration works.
@ -725,7 +809,9 @@ fmt.Printf("%c\n", r) // o
### Misusing trim functions (#38)
**TL;DR**: `strings.TrimRight`/`strings.TrimLeft` removes all the trailing/leading runes contained in a given set, whereas `strings.TrimSuffix`/`strings.TrimPrefix` returns a string without a provided suffix/prefix.
???+ info "TL;DR"
`strings.TrimRight`/`strings.TrimLeft` removes all the trailing/leading runes contained in a given set, whereas `strings.TrimSuffix`/`strings.TrimPrefix` returns a string without a provided suffix/prefix.
For example:
@ -745,7 +831,9 @@ On the other side, `strings.TrimSuffix` / `strings.TrimPrefix` returns a string
### Under-optimized strings concatenation (#39)
**TL;DR**: Concatenating a list of strings should be done with `strings.Builder` to prevent allocating a new string during each iteration.
???+ info "TL;DR"
Concatenating a list of strings should be done with `strings.Builder` to prevent allocating a new string during each iteration.
Lets consider a `concat` function that concatenates all the string elements of a slice using the `+=` operator:
@ -775,8 +863,9 @@ func concat(values []string) string {
During each iteration, we constructed the resulting string by calling the `WriteString` method that appends the content of value to its internal buffer, hence minimizing memory copying.
> [!NOTE]
> `WriteString` returns an error as the second output, but we purposely ignore it. Indeed, this method will never return a non-nil error. So whats the purpose of this method returning an error as part of its signature? `strings.Builder` imple- ments the `io.StringWriter` interface, which contains a single method: `WriteString(s string) (n int, err error)`. Hence, to comply with this interface, `WriteString` must return an error.
???+ note
`WriteString` returns an error as the second output, but we purposely ignore it. Indeed, this method will never return a non-nil error. So whats the purpose of this method returning an error as part of its signature? `strings.Builder` imple- ments the `io.StringWriter` interface, which contains a single method: `WriteString(s string) (n int, err error)`. Hence, to comply with this interface, `WriteString` must return an error.
Internally, `strings.Builder` holds a byte slice. Each call to `WriteString` results in a call to append on this slice. There are two impacts. First, this struct shouldnt be used concurrently, as the calls to `append` would lead to race conditions. The second impact is something that we saw in [mistake #21, "Inefficient slice initialization"](#inefficient-slice-initialization-21): if the future length of a slice is already known, we should preallocate it. For that purpose, `strings.Builder` exposes a method `Grow(n int)` to guarantee space for another `n` bytes:
@ -812,7 +901,9 @@ As we can see, the latest version is by far the most efficient: 99% faster than
### Useless string conversions (#40)
**TL;DR**: Remembering that the `bytes` package offers the same operations as the `strings` package can help avoid extra byte/string conversions.
???+ info "TL;DR"
Remembering that the `bytes` package offers the same operations as the `strings` package can help avoid extra byte/string conversions.
When choosing to work with a string or a `[]byte`, most programmers tend to favor strings for convenience. But most I/O is actually done with `[]byte`. For example, `io.Reader`, `io.Writer`, and `io.ReadAll` work with `[]byte`, not strings.
@ -822,7 +913,9 @@ When were wondering whether we should work with strings or `[]byte`, lets
### Substring and memory leaks (#41)
**TL;DR**: Using copies instead of substrings can prevent memory leaks, as the string returned by a substring operation will be backed by the same byte array.
???+ info "TL;DR"
Using copies instead of substrings can prevent memory leaks, as the string returned by a substring operation will be backed by the same byte array.
In mistake [#26, “Slices and memory leaks,”](#slice-and-memory-leaks--26-) we saw how slicing a slice or array may lead to memory leak situations. This principle also applies to string and substring opera- tions.
@ -834,7 +927,9 @@ We need to keep two things in mind while using the substring operation in Go. Fi
### Not knowing which type of receiver to use (#42)
**TL;DR**: The decision whether to use a value or a pointer receiver should be made based on factors such as the type, whether it has to be mutated, whether it contains a field that cant be copied, and how large the object is. When in doubt, use a pointer receiver.
???+ info "TL;DR"
The decision whether to use a value or a pointer receiver should be made based on factors such as the type, whether it has to be mutated, whether it contains a field that cant be copied, and how large the object is. When in doubt, use a pointer receiver.
Choosing between value and pointer receivers isnt always straightforward. Lets dis- cuss some of the conditions to help us choose.
@ -874,7 +969,9 @@ Of course, its impossible to be exhaustive, as there will always be edge case
### Never using named result parameters (#43)
**TL;DR**: Using named result parameters can be an efficient way to improve the readability of a function/method, especially if multiple result parameters have the same type. In some cases, this approach can also be convenient because named result parameters are initialized to their zero value. But be cautious about potential side effects.
???+ info "TL;DR"
Using named result parameters can be an efficient way to improve the readability of a function/method, especially if multiple result parameters have the same type. In some cases, this approach can also be convenient because named result parameters are initialized to their zero value. But be cautious about potential side effects.
When we return parameters in a function or a method, we can attach names to these parameters and use them as regular variables. When a result parameter is named, its initialized to its zero value when the function/method begins. With named result parameters, we can also call a naked return statement (without argu- ments). In that case, the current values of the result parameters are used as the returned values.
@ -895,7 +992,9 @@ In some cases, named result parameters can also increase readability: for exampl
### Unintended side effects with named result parameters (#44)
**TL;DR**: See [#43](#never-using-named-result-parameters-43).
???+ info "TL;DR"
See [#43](#never-using-named-result-parameters-43).
We mentioned why named result parameters can be useful in some situations. But as these result parameters are initialized to their zero value, using them can sometimes lead to subtle bugs if were not careful enough. For example, can you spot whats wrong with this code?
@ -924,7 +1023,9 @@ When using named result parameters, we must recall that each parameter is initia
### Returning a nil receiver (#45)
**TL;DR**: When returning an interface, be cautious about returning not a nil pointer but an explicit nil value. Otherwise, unintended consequences may result because the caller will receive a non-nil value.
???+ info "TL;DR"
When returning an interface, be cautious about returning not a nil pointer but an explicit nil value. Otherwise, unintended consequences may result because the caller will receive a non-nil value.
<!-- TODO -->
@ -932,7 +1033,9 @@ When using named result parameters, we must recall that each parameter is initia
### Using a filename as a function input (#46)
**TL;DR**: Designing functions to receive `io.Reader` types instead of filenames improves the reusability of a function and makes testing easier.
???+ info "TL;DR"
Designing functions to receive `io.Reader` types instead of filenames improves the reusability of a function and makes testing easier.
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 imple- mentation can be reused and easily tested.
@ -940,7 +1043,9 @@ Accepting a filename as a function input to read from a file should, in most cas
### Ignoring how `defer` arguments and receivers are evaluated (argument evaluation, pointer, and value receivers) (#47)
**TL;DR**: Passing a pointer to a `defer` function and wrapping a call inside a closure are two possible solutions to overcome the immediate evaluation of arguments and receivers.
???+ info "TL;DR"
Passing a pointer to a `defer` function and wrapping a call inside a closure are two possible solutions to overcome the immediate evaluation of arguments and receivers.
In a `defer` function the arguments are evaluated right away, not once the surrounding function returns. For example, in this code, we always call `notify` and `incrementCounter` with the same status: an empty string.
@ -1025,7 +1130,9 @@ Let's also note this behavior applies with method receiver: the receiver is eval
### Panicking (#48)
**TL;DR**: Using `panic` is an option to deal with errors in Go. However, it should only be used sparingly in unrecoverable conditions: for example, to signal a programmer error or when you fail to load a mandatory dependency.
???+ info "TL;DR"
Using `panic` is an option to deal with errors in Go. However, it should only be used sparingly in unrecoverable conditions: for example, to signal a programmer error or when you fail to load a mandatory dependency.
In Go, panic is a built-in function that stops the ordinary flow:
@ -1054,7 +1161,9 @@ Panicking in Go should be used sparingly. There are two prominent cases, one to
### Ignoring when to wrap an error (#49)
**TL;DR**: Wrapping an error allows you to mark an error and/or provide additional context. However, error wrapping creates potential coupling as it makes the source error available for the caller. If you want to prevent that, dont use error wrapping.
???+ info "TL;DR"
Wrapping an error allows you to mark an error and/or provide additional context. However, error wrapping creates potential coupling as it makes the source error available for the caller. If you want to prevent that, dont use error wrapping.
Since Go 1.13, the %w directive allows us to wrap errors conveniently. Error wrapping is about wrapping or packing an error inside a wrapper container that also makes the source error available. In general, the two main use cases for error wrapping are the following:
@ -1067,7 +1176,9 @@ When handling an error, we can decide to wrap it. Wrapping is about adding addit
### Comparing an error type inaccurately (#50)
**TL;DR**: If you use Go 1.13 error wrapping with the `%w` directive and `fmt.Errorf`, comparing an error against a type has to be done using `errors.As`. Otherwise, if the returned error you want to check is wrapped, it will fail the checks.
???+ info "TL;DR"
If you use Go 1.13 error wrapping with the `%w` directive and `fmt.Errorf`, comparing an error against a type has to be done using `errors.As`. Otherwise, if the returned error you want to check is wrapped, it will fail the checks.
<!-- TODO -->
@ -1075,7 +1186,9 @@ When handling an error, we can decide to wrap it. Wrapping is about adding addit
### Comparing an error value inaccurately (#51)
**TL;DR**: If you use Go 1.13 error wrapping with the `%w` directive and `fmt.Errorf`, comparing an error against or a value has to be done using `errors.As`. Otherwise, if the returned error you want to check is wrapped, it will fail the checks.
???+ info "TL;DR"
If you use Go 1.13 error wrapping with the `%w` directive and `fmt.Errorf`, comparing an error against or a value has to be done using `errors.As`. Otherwise, if the returned error you want to check is wrapped, it will fail the checks.
A sentinel error is an error defined as a global variable:
@ -1096,7 +1209,9 @@ If we use error wrapping in our application with the `%w` directive and `fmt.Err
### Handling an error twice (#52)
**TL;DR**: In most situations, an error should be handled only once. Logging an error is handling an error. Therefore, you have to choose between logging or returning an error. In many cases, error wrapping is the solution as it allows you to provide additional context to an error and return the source error.
???+ info "TL;DR"
In most situations, an error should be handled only once. Logging an error is handling an error. Therefore, you have to choose between logging or returning an error. In many cases, error wrapping is the solution as it allows you to provide additional context to an error and return the source error.
Handling an error multiple times is a mistake made frequently by developers, not spe- cifically in Go. This can cause situations where the same error is logged multiple times make debugging harder.
@ -1106,13 +1221,17 @@ Let's reming us that handling an error should be done only once. Logging an erro
### Not handling an error (#53)
**TL;DR**: 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.
???+ info "TL;DR"
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)
### Not handling `defer` errors (#54)
**TL;DR**: In many cases, you shouldnt ignore an error returned by a `defer` function. Either handle it directly or propagate it to the caller, depending on the context. If you want to ignore it, use the blank identifier.
???+ info "TL;DR"
In many cases, you shouldnt ignore an error returned by a `defer` function. Either handle it directly or propagate it to the caller, depending on the context. If you want to ignore it, use the blank identifier.
Consider the following code:
@ -1149,21 +1268,29 @@ _ = notify()
### Mixing up concurrency and parallelism (#55)
**TL;DR**: Understanding the fundamental differences between concurrency and parallelism is a cornerstone of the Go developers knowledge. Concurrency is about structure, whereas parallelism is about execution.
???+ info "TL;DR"
Understanding the fundamental differences between concurrency and parallelism is a cornerstone of the Go developers knowledge. Concurrency is about structure, whereas parallelism is about execution.
### [Thinking concurrency is always faster](https://teivah.medium.com/concurrency-isnt-always-faster-in-go-de325168907c) (#56)
**TL;DR**: To be a proficient developer, you must acknowledge that concurrency isnt 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.
???+ info "TL;DR"
To be a proficient developer, you must acknowledge that concurrency isnt 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/)
### Being puzzled about when to use channels or mutexes (#57)
**TL;DR**: Being aware of goroutine interactions can also be helpful when deciding between channels and mutexes. In general, parallel goroutines require synchronization and hence mutexes. Conversely, concurrent goroutines generally require coordination and orchestration and hence channels.
???+ info "TL;DR"
Being aware of goroutine interactions can also be helpful when deciding between channels and mutexes. In general, parallel goroutines require synchronization and hence mutexes. Conversely, concurrent goroutines generally require coordination and orchestration and hence channels.
### Not understanding race problems (data races vs. race conditions and the Go memory model) (#58)
**TL;DR**: 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 doesnt necessarily mean deterministic execution. When a behavior depends on the sequence or the timing of events that cant be controlled, this is a race condition.
???+ info "TL;DR"
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 doesnt necessarily mean deterministic execution. When a behavior depends on the sequence or the timing of events that cant be controlled, this is a race condition.
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.
@ -1171,13 +1298,17 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
### Not understanding the concurrency impacts of a workload type (#59)
**TL;DR**: 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.
???+ info "TL;DR"
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)
### Misunderstanding Go contexts (#60)
**TL;DR**: 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.
???+ info "TL;DR"
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)
@ -1185,83 +1316,111 @@ Understanding the Go memory model and the underlying guarantees in terms of orde
### Propagating an inappropriate context (#61)
**TL;DR**: 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.
???+ info "TL;DR"
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)
### Starting a goroutine without knowing when to stop it (#62)
**TL;DR**: Avoiding leaks means being mindful that whenever a goroutine is started, you should have a plan to stop it eventually.
???+ info "TL;DR"
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/)
### Not being careful with goroutines and loop variables (#63)
**TL;DR**: To avoid bugs with goroutines and loop variables, create local variables or call functions instead of closures.
???+ info "TL;DR"
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)
### Expecting a deterministic behavior using select and channels (#64)
**TL;DR**: 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.
???+ info "TL;DR"
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)
### Not using notification channels (#65)
**TL;DR**: Send notifications using a `chan struct{}` type.
???+ info "TL;DR"
Send notifications using a `chan struct{}` type.
### Not using nil channels (#66)
**TL;DR**: Using nil channels should be part of your concurrency toolset because it allows you to _remove_ cases from `select` statements, for example.
???+ info "TL;DR"
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)
### Being puzzled about channel size (#67)
**TL;DR**: Carefully decide on the right channel type to use, given a problem. Only unbuffered channels provide strong synchronization guarantees.
???+ info "TL;DR"
Carefully decide on the right channel type to use, given a problem. Only unbuffered channels provide strong synchronization guarantees.
You should have a good reason to specify a channel size other than one for buffered channels.
### Forgetting about possible side effects with string formatting (etcd data race example and deadlock) (#68)
**TL;DR**: Being aware that string formatting may lead to calling existing functions means watching out for possible deadlocks and other data races.
???+ info "TL;DR"
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)
### Creating data races with append (#69)
**TL;DR**: Calling `append` isnt always data-race-free; hence, it shouldnt be used concurrently on a shared slice.
???+ info "TL;DR"
Calling `append` isnt always data-race-free; hence, it shouldnt 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)
### Using mutexes inaccurately with slices and maps (#70)
**TL;DR**: Remembering that slices and maps are pointers can prevent common data races.
???+ info "TL;DR"
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)
### Misusing `sync.WaitGroup` (#71)
**TL;DR**: To accurately use `sync.WaitGroup`, call the `Add` method before spinning up goroutines.
???+ info "TL;DR"
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)
### Forgetting about `sync.Cond` (#72)
**TL;DR**: You can send repeated notifications to multiple goroutines with `sync.Cond`.
???+ info "TL;DR"
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)
### Not using `errgroup` (#73)
**TL;DR**: You can synchronize a group of goroutines and handle errors and contexts with the `errgroup` package.
???+ info "TL;DR"
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)
### Copying a `sync` type (#74)
**TL;DR**: `sync` types shouldnt be copied.
???+ info "TL;DR"
`sync` types shouldnt be copied.
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/09-concurrency-practice/74-copying-sync/main.go)
@ -1269,13 +1428,17 @@ You should have a good reason to specify a channel size other than one for buffe
### Providing a wrong time duration (#75)
**TL;DR**: 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.
???+ info "TL;DR"
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)
### `time.After` and memory leaks (#76)
**TL;DR**: 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.
???+ info "TL;DR"
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)
@ -1331,19 +1494,25 @@ You should have a good reason to specify a channel size other than one for buffe
### Not closing transient resources (HTTP body, `sql.Rows`, and `os.File`) (#79)
**TL;DR**: Eventually close all structs implementing `io.Closer` to avoid possible leaks.
???+ info "TL;DR"
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/)
### Forgetting the return statement after replying to an HTTP request (#80)
**TL;DR**: To avoid unexpected behaviors in HTTP handler implementations, make sure you dont miss the `return` statement if you want a handler to stop after `http.Error`.
???+ info "TL;DR"
To avoid unexpected behaviors in HTTP handler implementations, make sure you dont 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)
### Using the default HTTP client and server (#81)
**TL;DR**: For production-grade applications, dont use the default HTTP client and server implementations. These implementations are missing timeouts and behaviors that should be mandatory in production.
???+ info "TL;DR"
For production-grade applications, dont 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/)
@ -1351,33 +1520,45 @@ You should have a good reason to specify a channel size other than one for buffe
### Not categorizing tests (build tags, environment variables, and short mode) (#82)
**TL;DR**: 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.
???+ info "TL;DR"
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/)
### Not enabling the race flag (#83)
**TL;DR**: Enabling the `-race` flag is highly recommended when writing concurrent applications. Doing so allows you to catch potential data races that can lead to software bugs.
???+ info "TL;DR"
Enabling the `-race` flag is highly recommended when writing concurrent applications. Doing so allows you to catch potential data races that can lead to software bugs.
### Not using test execution modes (parallel and shuffle) (#84)
**TL;DR**: Using the `-parallel` flag is an efficient way to speed up tests, especially long-running ones. Use the `-shuffle` flag to help ensure that a test suite doesnt rely on wrong assumptions that could hide bugs.
???+ info "TL;DR"
Using the `-parallel` flag is an efficient way to speed up tests, especially long-running ones. Use the `-shuffle` flag to help ensure that a test suite doesnt rely on wrong assumptions that could hide bugs.
### Not using table-driven tests (#85)
**TL;DR**: 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.
???+ info "TL;DR"
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)
### Sleeping in unit tests (#86)
**TL;DR**: Avoid sleeps using synchronization to make a test less flaky and more robust. If synchronization isnt possible, consider a retry approach.
???+ info "TL;DR"
Avoid sleeps using synchronization to make a test less flaky and more robust. If synchronization isnt possible, consider a retry approach.
[Source code](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)
**TL;DR**: 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.
???+ info "TL;DR"
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/)
@ -1445,7 +1626,9 @@ You should have a good reason to specify a channel size other than one for buffe
### Not using fuzzing (community mistake)
**TL;DR**: Fuzzing is an efficient strategy to detect random, unexpected, or malformed inputs to complex functions and methods in order to discover vulnerabilities, bugs, or even potential crashes.
???+ info "TL;DR"
Fuzzing is an efficient strategy to detect random, unexpected, or malformed inputs to complex functions and methods in order to discover vulnerabilities, bugs, or even potential crashes.
Credits: [@jeromedoucet](https://github.com/jeromedoucet)
@ -1481,46 +1664,64 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
### Writing concurrent code that leads to false sharing (#92)
**TL;DR**: Knowing that lower levels of CPU caches arent shared across all the cores helps avoid performance-degrading patterns such as false sharing while writing concurrency code. Sharing memory is an illusion.
???+ info "TL;DR"
Knowing that lower levels of CPU caches arent 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/)
### Not taking into account instruction-level parallelism (#93)
**TL;DR**: 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.
???+ info "TL;DR"
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/)
### Not being aware of data alignment (#94)
**TL;DR**: 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).
???+ info "TL;DR"
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/)
### Not understanding stack vs. heap (#95)
**TL;DR**: 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.
???+ info "TL;DR"
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/)
### Not knowing how to reduce allocations (API change, compiler optimizations, and `sync.Pool`) (#96)
**TL;DR**: 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`.
???+ info "TL;DR"
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/)
### Not relying on inlining (#97)
**TL;DR**: Use the fast-path inlining technique to efficiently reduce the amortized time to call a function.
???+ info "TL;DR"
Use the fast-path inlining technique to efficiently reduce the amortized time to call a function.
### [Not using Go diagnostics tooling](https://medium.com/@teivah/profiling-and-execution-tracing-in-go-a5e646970f5b) (#98)
**TL;DR**: Rely on profiling and the execution tracer to understand how an application performs and the parts to optimize.
???+ info "TL;DR"
Rely on profiling and the execution tracer to understand how an application performs and the parts to optimize.
### Not understanding how the GC works (#99)
**TL;DR**: Understanding how to tune the GC can lead to multiple benefits such as handling sudden load increases more efficiently.
???+ info "TL;DR"
Understanding how to tune the GC can lead to multiple benefits such as handling sudden load increases more efficiently.
### Not understanding the impacts of running Go in Docker and Kubernetes (#100)
**TL;DR**: To help avoid CPU throttling when deployed in Docker and Kubernetes, keep in mind that Go isnt CFS-aware.
???+ info "TL;DR"
To help avoid CPU throttling when deployed in Docker and Kubernetes, keep in mind that Go isnt CFS-aware.

View file

@ -1,3 +1,3 @@
# ❤️ Go Jobs
# Go Jobs
Is your company hiring? [Sponsor](https://github.com/sponsors/teivah/sponsorships?sponsor=teivah&tier_id=316526&preview=true) this repository and let a significant audience of Go developers know about your opportunities in this section (book sales: +8k, website traffic: +2000 views and +400 unique visitors per week).

View file

@ -4,8 +4,6 @@
### 意外的变量隐藏 (#1)
Avoiding shadowed variables can help prevent mistakes like referencing the wrong variable or confusing readers.
避免变量隐藏(外部作用域变量被内部作用域同名变量隐藏),有助于避免变量引用错误,有助于他人阅读理解。
### 不必要的代码嵌套 (#2)
@ -58,8 +56,6 @@ Avoiding shadowed variables can help prevent mistakes like referencing the wrong
### 忽略了包名冲突 (#14)
To avoid naming collisions between variables and packages, leading to confusion or perhaps even bugs, use unique names for each one. If this isnt feasible, use an import alias to change the qualifier to differentiate the package name from the variable name, or think of a better name.
为了避免变量名和包名之间的冲突,导致混淆或甚至错误,应为每个变量和包使用唯一的名称。如果这不可行,可以考虑使用导入别名 `import importAlias 'importPath'`,以区分包名和变量名,或者考虑一个更好的变量名。
### 代码缺少文档 (#15)

View file

@ -1,13 +1,20 @@
site_name: 100 Go Mistakes
site_url: https://100go.co
repo_name: teivah/100-go-mistakes
theme:
name: material
custom_dir: overrides
favicon: Go-Logo_Fuchsia.svg
favicon: img/Go-Logo_LightBlue.svg
language: en
logo: img/Go-Logo_White.svg
icon:
repo: fontawesome/brands/github
features:
- navigation.tabs
- navigation.tabs.sticky
- search.highlight
- search.share
- search.suggest
palette:
# Palette toggle for light mode
- scheme: default
@ -42,14 +49,19 @@ extra:
- icon: fontawesome/brands/medium
link: http://blog.teivah.io
nav:
- Book:
- book.md
- chapter-1.md
- external.md
- Common Go Mistakes:
- index.md
- jobs.md
- Chinese (Simplified):
- zh/index.md
- external.md
- ❤️ Go Jobs:
- jobs.md
markdown_extensions:
- admonition
- pymdownx.details
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span

View file

@ -11,7 +11,7 @@
<link rel="icon" href="/Go-Logo_Fuchsia.svg">
<link rel="icon" href="/img/Go-Logo_LightBlue.svg">
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.3.1">
@ -88,7 +88,7 @@
<header class="md-header md-header--shadow" data-md-component="header">
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="/." title="100 Go Mistakes" class="md-header__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -187,12 +187,19 @@
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
@ -215,13 +222,78 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="/book/" class="md-tabs__link">
Book
</a>
</li>
<li class="md-tabs__item">
<a href="/." class="md-tabs__link">
Common Go Mistakes
</a>
</li>
<li class="md-tabs__item">
<a href="/jobs/" class="md-tabs__link">
❤️ Go Jobs
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
@ -229,8 +301,6 @@
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
@ -243,7 +313,9 @@
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="/." title="100 Go Mistakes" class="md-nav__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -260,7 +332,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
@ -272,12 +344,46 @@
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" >
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Book
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Book
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="/book/" class="md-nav__link">
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
@ -291,6 +397,7 @@
<li class="md-nav__item">
<a href="/chapter-1/" class="md-nav__link">
@ -310,12 +417,13 @@
<li class="md-nav__item">
<a href="/." class="md-nav__link">
<a href="/external/" class="md-nav__link">
<span class="md-ellipsis">
💡 Common Go Mistakes
External Resources
</span>
@ -325,20 +433,9 @@
</ul>
</nav>
<li class="md-nav__item">
<a href="/jobs/" class="md-nav__link">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
</a>
</li>
@ -357,9 +454,63 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Common Go Mistakes
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Common Go Mistakes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="/." class="md-nav__link">
<span class="md-ellipsis">
English
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
<span class="md-ellipsis">
@ -370,8 +521,8 @@
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_2">
<span class="md-nav__icon md-icon"></span>
Chinese (Simplified)
</label>
@ -405,16 +556,58 @@
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
❤️ Go Jobs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="/external/" class="md-nav__link">
<a href="/jobs/" class="md-nav__link">
<span class="md-ellipsis">
External Resources
Go Jobs
</span>
@ -423,6 +616,14 @@
</ul>
</nav>
</li>
</ul>
</nav>
</div>
@ -514,7 +715,7 @@
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "/", "features": [], "search": "/assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script id="__config" type="application/json">{"base": "/", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest"], "search": "/assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="/assets/javascripts/bundle.dff1b7c8.min.js"></script>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -15,7 +15,7 @@
<link rel="next" href="../chapter-1/">
<link rel="icon" href="../Go-Logo_Fuchsia.svg">
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.3.1">
@ -63,7 +63,7 @@
<meta property="og:type" content="website" >
<meta property="og:title" content="Book Presentation - 100 Go Mistakes" >
<meta property="og:title" content="Presentation - 100 Go Mistakes" >
<meta property="og:description" content="None" >
@ -79,7 +79,7 @@
<meta name="twitter:card" content="summary_large_image" >
<meta name="twitter:title" content="Book Presentation - 100 Go Mistakes" >
<meta name="twitter:title" content="Presentation - 100 Go Mistakes" >
<meta name="twitter:description" content="None" >
@ -109,7 +109,7 @@
<div data-md-component="skip">
<a href="#book-presentation" class="md-skip">
<a href="#presentation" class="md-skip">
Skip to content
</a>
@ -123,7 +123,7 @@
<header class="md-header md-header--shadow" data-md-component="header">
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="100 Go Mistakes" class="md-header__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -144,7 +144,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
</div>
@ -222,12 +222,19 @@
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
@ -250,13 +257,80 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
Book
</a>
</li>
<li class="md-tabs__item">
<a href=".." class="md-tabs__link">
Common Go Mistakes
</a>
</li>
<li class="md-tabs__item">
<a href="../jobs/" class="md-tabs__link">
❤️ Go Jobs
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
@ -264,8 +338,6 @@
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
@ -278,7 +350,9 @@
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="100 Go Mistakes" class="md-nav__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -295,7 +369,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
@ -309,6 +383,42 @@
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" checked>
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Book
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Book
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
@ -321,7 +431,7 @@
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
@ -332,7 +442,7 @@
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
@ -394,6 +504,7 @@
<li class="md-nav__item">
<a href="../chapter-1/" class="md-nav__link">
@ -413,12 +524,13 @@
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<a href="../external/" class="md-nav__link">
<span class="md-ellipsis">
💡 Common Go Mistakes
External Resources
</span>
@ -428,20 +540,9 @@
</ul>
</nav>
<li class="md-nav__item">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
</a>
</li>
@ -460,9 +561,63 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Common Go Mistakes
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Common Go Mistakes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
English
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
<span class="md-ellipsis">
@ -473,8 +628,8 @@
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_2">
<span class="md-nav__icon md-icon"></span>
Chinese (Simplified)
</label>
@ -508,16 +663,58 @@
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
❤️ Go Jobs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../external/" class="md-nav__link">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
External Resources
Go Jobs
</span>
@ -526,6 +723,14 @@
</ul>
</nav>
</li>
</ul>
</nav>
</div>
@ -598,7 +803,7 @@
<h1 id="book-presentation">Book Presentation</h1>
<h1 id="presentation">Presentation</h1>
<p>Source code and community space of <em>100 Go Mistakes and How to Avoid Them</em>, published by Manning in 2022.</p>
<p><img alt="" src="../img/cover.png" /></p>
<h2 id="description">Description</h2>
@ -704,7 +909,7 @@
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.dff1b7c8.min.js"></script>

View file

@ -14,10 +14,10 @@
<link rel="prev" href="../book/">
<link rel="next" href="..">
<link rel="next" href="../external/">
<link rel="icon" href="../Go-Logo_Fuchsia.svg">
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.3.1">
@ -125,7 +125,7 @@
<header class="md-header md-header--shadow" data-md-component="header">
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="100 Go Mistakes" class="md-header__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -224,12 +224,19 @@
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
@ -252,13 +259,80 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item md-tabs__item--active">
<a href="../book/" class="md-tabs__link">
Book
</a>
</li>
<li class="md-tabs__item">
<a href=".." class="md-tabs__link">
Common Go Mistakes
</a>
</li>
<li class="md-tabs__item">
<a href="../jobs/" class="md-tabs__link">
❤️ Go Jobs
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
@ -266,8 +340,6 @@
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
@ -280,7 +352,9 @@
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="100 Go Mistakes" class="md-nav__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -297,7 +371,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
@ -309,12 +383,48 @@
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" checked>
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Book
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Book
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../book/" class="md-nav__link">
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
@ -330,6 +440,7 @@
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
@ -470,12 +581,13 @@
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<a href="../external/" class="md-nav__link">
<span class="md-ellipsis">
💡 Common Go Mistakes
External Resources
</span>
@ -485,20 +597,9 @@
</ul>
</nav>
<li class="md-nav__item">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
</a>
</li>
@ -517,9 +618,63 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Common Go Mistakes
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Common Go Mistakes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
English
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
<span class="md-ellipsis">
@ -530,8 +685,8 @@
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_2">
<span class="md-nav__icon md-icon"></span>
Chinese (Simplified)
</label>
@ -565,16 +720,58 @@
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
❤️ Go Jobs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../external/" class="md-nav__link">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
External Resources
Go Jobs
</span>
@ -583,6 +780,14 @@
</ul>
</nav>
</li>
</ul>
</nav>
</div>
@ -711,14 +916,17 @@
<h1 id="go-simple-to-learn-but-hard-to-master">Go: Simple to learn but hard to master</h1>
<p>This chapter covers
* What makes Go an efficient, scalable, and productive language
* Exploring why Go is simple to learn but hard to master
* Presenting the common types of mistakes made by developers</p>
<p>This chapter covers</p>
<ul>
<li>What makes Go an efficient, scalable, and productive language</li>
<li>Exploring why Go is simple to learn but hard to master</li>
<li>Presenting the common types of mistakes made by developers</li>
</ul>
<p>Making mistakes is part of everyones life. As Albert Einstein once said,</p>
<blockquote>
<div class="admonition quote">
<p class="admonition-title">Albert Einstein</p>
<p>A person who never made a mistake never tried anything new.</p>
</blockquote>
</div>
<p>What matters in the end isnt the number of mistakes we make, but our capacity to learn from them. This assertion also applies to programming. The seniority we acquire in a language isnt a magical process; it involves making many mistakes and learning from them. The purpose of this book is centered around this idea. It will help you, the reader, become a more proficient Go developer by looking at and learning from 100 common mistakes people make in many areas of the language.</p>
<p>This chapter presents a quick refresher as to why Go has become mainstream over the years. Well discuss why, despite Go being considered simple to learn, mastering its nuances can be challenging. Finally, well introduce the concepts this book covers.</p>
<h2 id="go-outline">Go outline</h2>
@ -726,9 +934,10 @@
<p>Software engineering has evolved considerably during the past decades. Most modern systems are no longer written by a single person but by teams consisting of multiple programmers—sometimes even hundreds, if not thousands. Nowadays, code must be readable, expressive, and maintainable to guarantee a systems durability over the years. Meanwhile, in our fast-moving world, maximizing agility and reducing the time to market is critical for most organizations. Programming should also follow this trend, and companies strive to ensure that software engineers are as productive as possible when reading, writing, and maintaining code.</p>
<p>In response to these challenges, Google created the Go programming language in 2007. Since then, many organizations have adopted the language to support various use cases: APIs, automation, databases, CLIs (command-line interfaces), and so on. Many today consider Go the language of the cloud.</p>
<p>Feature-wise, Go has no type inheritance, no exceptions, no macros, no partial functions, no support for lazy variable evaluation or immutability, no operator overloading, no pattern matching, and on and on. Why are these features missing from the language? The official <a href="https://go.dev/doc/faq">Go FAQ</a> gives us some insight:</p>
<blockquote>
<div class="admonition quote">
<p class="admonition-title">Go FAQ</p>
<p>Why does Go not have feature X? Your favorite feature may be missing because it doesnt fit, because it affects compilation speed or clarity of design, or because it would make the fundamental system model too difficult.</p>
</blockquote>
</div>
<p>Judging the quality of a programming language via its number of features is probably not an accurate metric. At least, its not an objective of Go. Instead, Go utilizes a few essential characteristics when adopting a language at scale for an organization. These include the following:</p>
<ul>
<li><em>Stability</em>—Even though Go receives frequent updates (including improvements and security patches), it remains a stable language. Some may even consider this one of the best features of the language.</li>
@ -749,10 +958,10 @@
<p>Why should we read a book about common Go mistakes? Why not deepen our knowledge with an ordinary book that would dig into different topics?</p>
<p>In a 2011 article, neuroscientists proved that the best time for brain growth is when were facing mistakes. Havent we all experienced the process of learning from a mistake and recalling that occasion after months or even years, when some context related to it? As presented in another article, by Janet Metcalfe, this happens because mistakes have a facilitative effect. The main idea is that we can remember not only the error but also the context surrounding the mistake. This is one of the reasons why learning from mistakes is so efficient.</p>
<p>To strengthen this facilitative effect, this book accompanies each mistake as much as possible with real-world examples. This book isnt only about theory; it also helps us get better at avoiding mistakes and making more well-informed, conscious decisions because we now understand the rationale behind them.</p>
<blockquote>
<div class="admonition quote">
<p class="admonition-title">Unknown</p>
<p>Tell me and I forget. Teach me and I remember. Involve me and I learn.</p>
</blockquote>
<p><em>- Unknown</em></p>
</div>
<p>This book presents seven main categories of mistakes. Overall, the mistakes can be classified as</p>
<ul>
<li>Bugs</li>
@ -860,7 +1069,7 @@
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.dff1b7c8.min.js"></script>

View file

@ -11,11 +11,13 @@
<link rel="canonical" href="https://100go.co/external/">
<link rel="prev" href="../zh/">
<link rel="prev" href="../chapter-1/">
<link rel="next" href="..">
<link rel="icon" href="../Go-Logo_Fuchsia.svg">
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.3.1">
@ -123,7 +125,7 @@
<header class="md-header md-header--shadow" data-md-component="header">
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="100 Go Mistakes" class="md-header__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -222,12 +224,19 @@
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
@ -250,13 +259,80 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item md-tabs__item--active">
<a href="../book/" class="md-tabs__link">
Book
</a>
</li>
<li class="md-tabs__item">
<a href=".." class="md-tabs__link">
Common Go Mistakes
</a>
</li>
<li class="md-tabs__item">
<a href="../jobs/" class="md-tabs__link">
❤️ Go Jobs
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
@ -264,8 +340,6 @@
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
@ -278,7 +352,9 @@
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="100 Go Mistakes" class="md-nav__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -295,7 +371,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
@ -307,12 +383,48 @@
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" checked>
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Book
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Book
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../book/" class="md-nav__link">
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
@ -326,6 +438,7 @@
<li class="md-nav__item">
<a href="../chapter-1/" class="md-nav__link">
@ -345,104 +458,6 @@
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
💡 Common Go Mistakes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Chinese (Simplified)
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Chinese (Simplified)
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../zh/" class="md-nav__link">
<span class="md-ellipsis">
100个Go常见错误及如何避免
</span>
</a>
</li>
</ul>
</nav>
</li>
@ -526,6 +541,198 @@
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Common Go Mistakes
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Common Go Mistakes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
English
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
<span class="md-ellipsis">
Chinese (Simplified)
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_2">
<span class="md-nav__icon md-icon"></span>
Chinese (Simplified)
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../zh/" class="md-nav__link">
<span class="md-ellipsis">
100个Go常见错误及如何避免
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
❤️ Go Jobs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
Go Jobs
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
@ -692,7 +899,7 @@
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.dff1b7c8.min.js"></script>

File diff suppressed because it is too large Load diff

View file

@ -11,13 +11,11 @@
<link rel="canonical" href="https://100go.co/jobs/">
<link rel="prev" href="..">
<link rel="prev" href="../zh/">
<link rel="next" href="../zh/">
<link rel="icon" href="../Go-Logo_Fuchsia.svg">
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.3.1">
@ -65,7 +63,7 @@
<meta property="og:type" content="website" >
<meta property="og:title" content="❤️ Go Jobs - 100 Go Mistakes" >
<meta property="og:title" content="Go Jobs - 100 Go Mistakes" >
<meta property="og:description" content="None" >
@ -81,7 +79,7 @@
<meta name="twitter:card" content="summary_large_image" >
<meta name="twitter:title" content="❤️ Go Jobs - 100 Go Mistakes" >
<meta name="twitter:title" content="Go Jobs - 100 Go Mistakes" >
<meta name="twitter:description" content="None" >
@ -125,7 +123,7 @@
<header class="md-header md-header--shadow" data-md-component="header">
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="100 Go Mistakes" class="md-header__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -146,7 +144,7 @@
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
❤️ Go Jobs
Go Jobs
</span>
</div>
@ -224,12 +222,19 @@
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
@ -252,13 +257,80 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../book/" class="md-tabs__link">
Book
</a>
</li>
<li class="md-tabs__item">
<a href=".." class="md-tabs__link">
Common Go Mistakes
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
❤️ Go Jobs
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
@ -266,8 +338,6 @@
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
@ -280,7 +350,9 @@
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="100 Go Mistakes" class="md-nav__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -297,7 +369,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
@ -309,12 +381,46 @@
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" >
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Book
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Book
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../book/" class="md-nav__link">
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
@ -328,6 +434,7 @@
<li class="md-nav__item">
<a href="../chapter-1/" class="md-nav__link">
@ -347,12 +454,13 @@
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<a href="../external/" class="md-nav__link">
<span class="md-ellipsis">
💡 Common Go Mistakes
External Resources
</span>
@ -362,29 +470,8 @@
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
</a>
</ul>
</nav>
</li>
@ -404,9 +491,63 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Common Go Mistakes
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Common Go Mistakes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
English
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
<span class="md-ellipsis">
@ -417,8 +558,8 @@
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_2">
<span class="md-nav__icon md-icon"></span>
Chinese (Simplified)
</label>
@ -452,20 +593,82 @@
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../external/" class="md-nav__link">
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" checked>
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
External Resources
❤️ Go Jobs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
❤️ Go Jobs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Go Jobs
</span>
</a>
</li>
</ul>
</nav>
</li>
@ -506,7 +709,7 @@
<h1 id="go-jobs">❤️ Go Jobs</h1>
<h1 id="go-jobs">Go Jobs</h1>
<p>Is your company hiring? <a href="https://github.com/sponsors/teivah/sponsorships?sponsor=teivah&amp;tier_id=316526&amp;preview=true">Sponsor</a> this repository and let a significant audience of Go developers know about your opportunities in this section (book sales: +8k, website traffic: +2000 views and +400 unique visitors per week).</p>
@ -577,7 +780,7 @@
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.dff1b7c8.min.js"></script>

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -11,13 +11,13 @@
<link rel="canonical" href="https://100go.co/zh/">
<link rel="prev" href="../jobs/">
<link rel="prev" href="..">
<link rel="next" href="../external/">
<link rel="next" href="../jobs/">
<link rel="icon" href="../Go-Logo_Fuchsia.svg">
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.3.1">
@ -125,7 +125,7 @@
<header class="md-header md-header--shadow" data-md-component="header">
<header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="100 Go Mistakes" class="md-header__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -224,12 +224,19 @@
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
@ -252,13 +259,80 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
</nav>
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../book/" class="md-tabs__link">
Book
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href=".." class="md-tabs__link">
Common Go Mistakes
</a>
</li>
<li class="md-tabs__item">
<a href="../jobs/" class="md-tabs__link">
❤️ Go Jobs
</a>
</li>
</ul>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
@ -266,8 +340,6 @@
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
@ -280,7 +352,9 @@
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="100 Go Mistakes" class="md-nav__button md-logo" aria-label="100 Go Mistakes" data-md-component="logo">
@ -297,7 +371,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</div>
<div class="md-source__repository">
GitHub
teivah/100-go-mistakes
</div>
</a>
</div>
@ -309,12 +383,46 @@
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_1" >
<label class="md-nav__link" for="__nav_1" id="__nav_1_label" tabindex="0">
<span class="md-ellipsis">
Book
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_1_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_1">
<span class="md-nav__icon md-icon"></span>
Book
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../book/" class="md-nav__link">
<span class="md-ellipsis">
Book Presentation
Presentation
</span>
@ -328,6 +436,7 @@
<li class="md-nav__item">
<a href="../chapter-1/" class="md-nav__link">
@ -347,12 +456,13 @@
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<a href="../external/" class="md-nav__link">
<span class="md-ellipsis">
💡 Common Go Mistakes
External Resources
</span>
@ -362,20 +472,9 @@
</ul>
</nav>
<li class="md-nav__item">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
</a>
</li>
@ -396,9 +495,65 @@
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" checked>
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" checked>
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Common Go Mistakes
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Common Go Mistakes
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
English
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" checked>
<label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
<span class="md-ellipsis">
@ -409,8 +564,8 @@
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_5">
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_2_2">
<span class="md-nav__icon md-icon"></span>
Chinese (Simplified)
</label>
@ -1334,16 +1489,58 @@
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
❤️ Go Jobs
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
❤️ Go Jobs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../external/" class="md-nav__link">
<a href="../jobs/" class="md-nav__link">
<span class="md-ellipsis">
External Resources
Go Jobs
</span>
@ -1352,6 +1549,14 @@
</ul>
</nav>
</li>
</ul>
</nav>
</div>
@ -2249,7 +2454,6 @@
<h1 id="100go">100个Go常见错误及如何避免</h1>
<h2 id="_1">代码及工程组织</h2>
<h3 id="1">意外的变量隐藏 (#1)</h3>
<p>Avoiding shadowed variables can help prevent mistakes like referencing the wrong variable or confusing readers.</p>
<p>避免变量隐藏(外部作用域变量被内部作用域同名变量隐藏),有助于避免变量引用错误,有助于他人阅读理解。</p>
<h3 id="2">不必要的代码嵌套 (#2)</h3>
<p>避免不必要的、过多的嵌套层次,并且让正常代码路径尽量左对齐(而不是放在分支路径中),有助于构建可读性更好的代码。</p>
@ -2276,7 +2480,6 @@
<h3 id="13">创建工具包 (#13)</h3>
<p>命名是软件设计开发中非常重要的一个部分,创建一些名如 <code>common</code><code>util</code><code>shared</code> 之类的包名并不会给读者带来太大价值,应该将这些包名重构为更清晰、更聚焦的包名。</p>
<h3 id="14">忽略了包名冲突 (#14)</h3>
<p>To avoid naming collisions between variables and packages, leading to confusion or perhaps even bugs, use unique names for each one. If this isnt feasible, use an import alias to change the qualifier to differentiate the package name from the variable name, or think of a better name.</p>
<p>为了避免变量名和包名之间的冲突,导致混淆或甚至错误,应为每个变量和包使用唯一的名称。如果这不可行,可以考虑使用导入别名 <code>import importAlias 'importPath'</code>,以区分包名和变量名,或者考虑一个更好的变量名。</p>
<h3 id="15">代码缺少文档 (#15)</h3>
<p>为了让使用方、维护人员能更清晰地了解你的代码的意图导出的元素函数、类型、字段需要添加godoc注释。</p>
@ -2652,7 +2855,7 @@
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest"], "search": "../assets/javascripts/workers/search.dfff1995.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.dff1b7c8.min.js"></script>