Adding section
BIN
.cache/plugin/social/32eacdda64c3f30ce5c3faa1182316b2.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
135
docs/20-slice.md
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
title: Not understanding slice length and capacity (#20)
|
||||
---
|
||||
|
||||
# Not understanding slice length and capacity
|
||||
|
||||
It’s pretty common for Go developers to mix slice length and capacity or not understand them thoroughly. Assimilating these two concepts is essential for efficiently handling core operations such as slice initialization and adding elements with append, copying, or slicing. This misunderstanding can lead to using slices suboptimally or even to memory leaks.
|
||||
|
||||
In Go, a slice is backed by an array. That means the slice’s data is stored contiguously in an array data structure. A slice also handles the logic of adding an element if the backing array is full or shrinking the backing array if it’s almost empty.
|
||||
|
||||
Internally, a slice holds a pointer to the backing array plus a length and a capacity. The length is the number of elements the slice contains, whereas the capacity is the number of elements in the backing array, counting from the first element in the slice. Let’s go through a few examples to make things clearer. First, let’s initialize a slice with a given length and capacity:
|
||||
|
||||
```go
|
||||
s := make([]int, 3, 6) // Three-length, six-capacity slice
|
||||
```
|
||||
|
||||
The first argument, representing the length, is mandatory. However, the second argument representing the capacity is optional. Figure 1 shows the result of this code in memory.
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 1: A three-length, six-capacity slice.</figcaption>
|
||||
</figure>
|
||||
|
||||
In this case, `make` creates an array of six elements (the capacity). But because the length was set to 3, Go initializes only the first three elements. Also, because the slice is an `[]int` type, the first three elements are initialized to the zeroed value of an `int`: 0. The grayed elements are allocated but not yet used.
|
||||
|
||||
If we print this slice, we get the elements within the range of the length, `[0 0 0]`. If we set `s[1]` to 1, the second element of the slice updates without impacting its length or capacity. Figure 2 illustrates this.
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 2: Updating the slice’s second element: s[1] = 1.</figcaption>
|
||||
</figure>
|
||||
|
||||
However, accessing an element outside the length range is forbidden, even though it’s already allocated in memory. For example, `s[4]` = 0 would lead to the following panic:
|
||||
|
||||
```
|
||||
panic: runtime error: index out of range [4] with length 3
|
||||
```
|
||||
|
||||
How can we use the remaining space of the slice? By using the `append` built-in function:
|
||||
|
||||
```go
|
||||
s = append(s, 2)
|
||||
```
|
||||
|
||||
This code appends to the existing `s` slice a new element. It uses the first grayed element (which was allocated but not yet used) to store element 2, as figure 3 shows.
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 3: Appending an element to s.</figcaption>
|
||||
</figure>
|
||||
|
||||
The length of the slice is updated from 3 to 4 because the slice now contains four elements. Now, what happens if we add three more elements so that the backing array isn’t large enough?
|
||||
|
||||
```go
|
||||
s = append(s, 3, 4, 5)
|
||||
fmt.Println(s)
|
||||
```
|
||||
|
||||
If we run this code, we see that the slice was able to cope with our request:
|
||||
|
||||
```
|
||||
[0 1 0 2 3 4 5]
|
||||
```
|
||||
|
||||
Because an array is a fixed-size structure, it can store the new elements until element 4. When we want to insert element 5, the array is already full: Go internally creates another array by doubling the capacity, copying all the elements, and then inserting element 5. Figure 4 shows this process.
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 4: Because the initial backing array is full, Go creates another array and copies all the elements.</figcaption>
|
||||
</figure>
|
||||
|
||||
The slice now references the new backing array. What will happen to the previous backing array? If it’s no longer referenced, it’s eventually freed by the garbage collector (GC) if allocated on the heap. (We discuss heap memory in mistake #95, “[Not understanding stack vs. heap](https://100go.co#not-understanding-stack-vs-heap-95),” and we look at how the GC works in mistake #99, “[Not understanding how the GC works](https://100go.co#not-understanding-how-the-gc-works-99).”)
|
||||
|
||||
What happens with slicing? Slicing is an operation done on an array or a slice, providing a half-open range; the first index is included, whereas the second is excluded. The following example shows the impact, and figure 5 displays the result in memory:
|
||||
|
||||
```go
|
||||
s1 := make([]int, 3, 6) // Three-length, six-capacity slice
|
||||
s2 := s1[1:3] // Slicing from indices 1 to 3
|
||||
```
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 5: The slices s1 and s2 reference the same backing array with different lengths and capacities.</figcaption>
|
||||
</figure>
|
||||
|
||||
First, `s1` is created as a three-length, six-capacity slice. When `s2` is created by slicing `s1`, both slices reference the same backing array. However, `s2` starts from a different index, 1. Therefore, its length and capacity (a two-length, five-capacity slice) differ from s1. If we update `s1[1]` or `s2[0]`, the change is made to the same array, hence, visible in both slices, as figure 6 shows.
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 6: Because s1 and s2 are backed by the same array, updating a common element makes the change visible in both slices.</figcaption>
|
||||
</figure>
|
||||
|
||||
Now, what happens if we append an element to `s2`? Does the following code change `s1` as well?
|
||||
|
||||
```go
|
||||
s2 = append(s2, 2)
|
||||
```
|
||||
|
||||
The shared backing array is modified, but only the length of `s2` changes. Figure 7 shows the result of appending an element to `s2`.
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 7: Appending an element to s2.</figcaption>
|
||||
</figure>
|
||||
|
||||
`s1` remains a three-length, six-capacity slice. Therefore, if we print `s1` and `s2`, the added element is only visible for `s2`:
|
||||
|
||||
```go
|
||||
s1=[0 1 0], s2=[1 0 2]
|
||||
```
|
||||
|
||||
It’s important to understand this behavior so that we don’t make wrong assumptions while using append.
|
||||
|
||||
???+ note
|
||||
|
||||
In these examples, the backing array is internal and not available directly to the Go developer. The only exception is when a slice is created from slicing an existing array.
|
||||
|
||||
One last thing to note: what if we keep appending elements to `s2` until the backing array is full? What will the state be, memory-wise? Let’s add three more elements so that the backing array will not have enough capacity:
|
||||
|
||||
```go
|
||||
s2 = append(s2, 3)
|
||||
s2 = append(s2, 4) // At this stage, the backing is already full
|
||||
s2 = append(s2, 5)
|
||||
```
|
||||
|
||||
This code leads to creating another backing array. Figure 8 displays the results in memory.
|
||||
|
||||
<figure markdown>
|
||||

|
||||
<figcaption>Figure 8: Appending elements to s2 until the backing array is full.</figcaption>
|
||||
</figure>
|
||||
|
||||
`s1` and `s2` now reference two different arrays. As `s1` is still a three-length, six-capacity slice, it still has some available buffer, so it keeps referencing the initial array. Also, the new backing array was made by copying the initial one from the first index of `s2`. That’s why the new array starts with element 1, not 0.
|
||||
|
||||
To summarize, 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. Adding an element to a full slice (length == capacity) leads to creating a new backing array with a new capacity, copying all the elements from the previous array, and updating the slice pointer to the new array.
|
||||
|
|
@ -25,7 +25,7 @@ If you're a Go developer looking to improve your skills, this book is for you. W
|
|||
## Where to Buy?
|
||||
|
||||
* _100 Go Mistakes and How to Avoid Them_ (🇬🇧 edition: paper, digital, or audiobook)
|
||||
* [Manning](https://www.manning.com/books/100-go-mistakes-and-how-to-avoid-them)
|
||||
* [Manning](https://www.manning.com/books/100-go-mistakes-and-how-to-avoid-them) (make sure to use my personal discount code for -35%: `au35har`)
|
||||
* [O’Reilly](https://www.oreilly.com/library/view/100-go-mistakes/9781617299599/)
|
||||
* Amazon: [.com](https://www.amazon.com/dp/1617299596), [.co.uk](https://www.amazon.co.uk/dp/B0BBSNJR6B), [.de](https://www.amazon.de/dp/B0BBHQD8BQ), [.fr](https://www.amazon.fr/100-Mistakes-How-Avoid-Them/dp/1617299596), [.in](https://www.amazon.in/dp/B0BBHQD8BQ), [.co.jp](https://www.amazon.co.jp/dp/B0BBHQD8BQ), [.es](https://www.amazon.es/dp/B0BBHQD8BQ), [.it](https://www.amazon.it/dp/B0BBHQD8BQ), [.com.br](https://www.amazon.com.br/dp/B0BBHQD8BQ)
|
||||
|
||||
|
|
|
|||
BIN
docs/img/slice-1.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
docs/img/slice-2.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
docs/img/slice-3.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
docs/img/slice-4.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/img/slice-5.png
Normal file
|
After Width: | Height: | Size: 8 KiB |
BIN
docs/img/slice-6.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
docs/img/slice-7.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
docs/img/slice-8.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -88,6 +88,7 @@ Writing readable code is an important challenge for every developer. Striving to
|
|||
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.
|
||||
|
||||
Init functions can lead to some issues:
|
||||
|
||||
* They can limit error management.
|
||||
* They can complicate how to implement tests (for example, an external dependency must be set up, which may not be necessary for the scope of unit tests).
|
||||
* If the initialization requires us to set a state, that has to be done through global variables.
|
||||
|
|
@ -199,6 +200,7 @@ promoted to `Foo`. Therefore, Baz becomes available from Foo.
|
|||
What can we say about type embedding? First, let’s note that it’s rarely a necessity, and it means that whatever the use case, we can probably solve it as well without type embedding. Type embedding is mainly used for convenience: in most cases, to promote behaviors.
|
||||
|
||||
If we decide to use type embedding, we need to keep two main constraints in mind:
|
||||
|
||||
* It shouldn’t be used solely as some syntactic sugar to simplify accessing a field (such as `Foo.Baz()` instead of `Foo.Bar.Baz()`). If this is the only rationale, let’s not embed the inner type and use a field instead.
|
||||
* It shouldn’t promote data (fields) or a behavior (methods) we want to hide from the outside: for example, if it allows clients to access a locking behavior that should remain private to the struct.
|
||||
|
||||
|
|
@ -213,6 +215,7 @@ Using type embedding consciously by keeping these constraints in mind can help a
|
|||
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.
|
||||
* Each option is a function that returns the same type: `type Option func(options *options)` error. For example, `WithPort` accepts an `int` argument that represents the port and returns an `Option` type that represents how to update the `options` struct.
|
||||
|
||||
|
|
@ -327,16 +330,17 @@ Documenting our code shouldn’t be a constraint. We should take the opportunity
|
|||
A linter is an automatic tool to analyze code and catch errors. The scope of this section isn’t 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.
|
||||
|
||||
However, if you’re not a regular user of linters, here is a list that you may want to use daily:
|
||||
* https://golang.org/cmd/vet/—A standard Go analyzer
|
||||
* https://github.com/kisielk/errcheck—An error checker
|
||||
* https://github.com/fzipp/gocyclo—A cyclomatic complexity analyzer
|
||||
* https://github.com/jgautheron/goconst—A repeated string constants analyzer
|
||||
|
||||
* [https://golang.org/cmd/vet](https://golang.org/cmd/vet)—A standard Go analyzer
|
||||
* [https://github.com/kisielk/errcheck](https://github.com/kisielk/errcheck)—An error checker
|
||||
* [https://github.com/fzipp/gocyclo](https://github.com/fzipp/gocyclo)—A cyclomatic complexity analyzer
|
||||
* [https://github.com/jgautheron/goconst](https://github.com/jgautheron/goconst)—A repeated string constants analyzer
|
||||
*
|
||||
Besides linters, we should also use code formatters to fix code style. Here is a list of some code formatters for you to try:
|
||||
* https://golang.org/cmd/gofmt/—A standard Go code formatter
|
||||
* https://godoc.org/golang.org/x/tools/cmd/goimports—A standard Go imports formatter
|
||||
* [https://golang.org/cmd/gofmt](https://golang.org/cmd/gofmt)—A standard Go code formatter
|
||||
* [https://godoc.org/golang.org/x/tools/cmd/goimports](https://godoc.org/golang.org/x/tools/cmd/goimports)—A standard Go imports formatter
|
||||
*
|
||||
Meanwhile, we should also look at golangci-lint (https://github.com/golangci/ golangci-lint). It’s a linting tool that provides a facade on top of many useful linters and formatters. Also, it allows running the linters in parallel to improve analysis speed, which is quite handy.
|
||||
Meanwhile, we should also look at golangci-lint ([https://github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint)). It’s a linting tool that provides a facade on top of many useful linters and formatters. Also, it allows running the linters in parallel to improve analysis speed, which is quite handy.
|
||||
|
||||
Linters and formatters are a powerful way to improve the quality and consistency of our codebase. Let’s take the time to understand which one we should use and make sure we automate their execution (such as a CI or Git precommit hook).
|
||||
|
||||
|
|
@ -346,11 +350,12 @@ Linters and formatters are a powerful way to improve the quality and consistency
|
|||
|
||||
???+ 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`.
|
||||
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`).
|
||||
|
||||
We should also note the other integer literal representations:
|
||||
|
||||
* _Binary_—Uses a `0b` or `0B` prefix (for example, `0b100` is equal to 4 in base 10)
|
||||
* _Hexadecimal_—Uses an `0x` or `0X` prefix (for example, `0xF` is equal to 15 in base 10)
|
||||
* _Imaginary_—Uses an `i` suffix (for example, `3i`)
|
||||
|
|
@ -397,6 +402,7 @@ fmt.Println(n * n)
|
|||
We may expect this code to print the result of 1.0001 * 1.0001 = 1.00020001, right? However, running it on most x86 processors prints 1.0002, instead.
|
||||
|
||||
Because Go’s `float32` and `float64` types are approximations, we have to bear a few rules in mind:
|
||||
|
||||
* When comparing two floating-point numbers, check that their difference is within an acceptable range.
|
||||
* When performing additions or subtractions, group operations with a similar order of magnitude for better accuracy.
|
||||
* To favor accuracy, if a sequence of operations requires addition, subtraction, multiplication, or division, perform the multiplication and division operations first.
|
||||
|
|
@ -409,7 +415,7 @@ Because Go’s `float32` and `float64` types are approximations, we have to bear
|
|||
|
||||
Understanding the difference between slice length and capacity should be part of a Go developer’s core knowledge. The slice length is the number of available elements in the slice, whereas the slice capacity is the number of elements in the backing array.
|
||||
|
||||
<!-- TODO -->
|
||||
Read the full section [here](20-slice.md).
|
||||
|
||||
[Source code](https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/20-slice-length-cap/main.go)
|
||||
|
||||
|
|
@ -524,6 +530,7 @@ Read the full section [here](28-maps-memory-leaks.md).
|
|||
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.
|
||||
|
||||
It’s 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.
|
||||
* _Numerics (int, float, and complex types)_—Compare whether two numerics are equal.
|
||||
* _Strings_—Compare whether two strings are equal.
|
||||
|
|
@ -553,6 +560,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
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
|
||||
* Array
|
||||
* Pointer to an array
|
||||
|
|
@ -603,6 +611,7 @@ When iterating over a data structure using a `range` loop, we must recall that a
|
|||
???+ info "TL;DR"
|
||||
|
||||
To ensure predictable outputs when using maps, remember that a map data structure:
|
||||
|
||||
* Doesn’t order the data by keys
|
||||
* Doesn’t preserve the insertion order
|
||||
* Doesn’t have a deterministic iteration order
|
||||
|
|
@ -1692,7 +1701,7 @@ Credits: [@jeromedoucet](https://github.com/jeromedoucet)
|
|||
|
||||
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)
|
||||
### Not using Go diagnostics tooling (#98)
|
||||
|
||||
???+ info "TL;DR"
|
||||
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ nav:
|
|||
- index.md
|
||||
- Full Sections:
|
||||
- 9-generics.md
|
||||
- 20-slice.md
|
||||
- 28-maps-memory-leaks.md
|
||||
- 89-benchmarks.md
|
||||
- 98-profiling-execution-tracing.md
|
||||
|
|
|
|||
993
site/20-slice/index.html
Normal file
|
|
@ -0,0 +1,993 @@
|
|||
|
||||
<!doctype html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
|
||||
|
||||
|
||||
<link rel="canonical" href="https://100go.co/20-slice/">
|
||||
|
||||
|
||||
<link rel="prev" href="../9-generics/">
|
||||
|
||||
|
||||
<link rel="next" href="../28-maps-memory-leaks/">
|
||||
|
||||
|
||||
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
|
||||
<meta name="generator" content="mkdocs-1.5.2, mkdocs-material-9.3.1">
|
||||
|
||||
|
||||
<title>100 Go Mistakes</title>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/main.046329b4.min.css">
|
||||
|
||||
|
||||
<link rel="stylesheet" href="../assets/stylesheets/palette.85d0ee34.min.css">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
|
||||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||||
|
||||
|
||||
|
||||
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script id="__analytics">function __md_analytics(){function n(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],n("js",new Date),n("config","G-HMY1HYDM93"),document.addEventListener("DOMContentLoaded",function(){document.forms.search&&document.forms.search.query.addEventListener("blur",function(){this.value&&n("event","search",{search_term:this.value})}),document$.subscribe(function(){var a=document.forms.feedback;if(void 0!==a)for(var e of a.querySelectorAll("[type=submit]"))e.addEventListener("click",function(e){e.preventDefault();var t=document.location.pathname,e=this.getAttribute("data-md-value");n("event","feedback",{page:t,data:e}),a.firstElementChild.disabled=!0;e=a.querySelector(".md-feedback__note [data-md-value='"+e+"']");e&&(e.hidden=!1)}),a.hidden=!1}),location$.subscribe(function(e){n("config","G-HMY1HYDM93",{page_path:e.pathname})})});var e=document.createElement("script");e.async=!0,e.src="https://www.googletagmanager.com/gtag/js?id=G-HMY1HYDM93",document.getElementById("__analytics").insertAdjacentElement("afterEnd",e)}</script>
|
||||
|
||||
<script>"undefined"!=typeof __md_analytics&&__md_analytics()</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<meta property="og:type" content="website" >
|
||||
|
||||
<meta property="og:title" content="Not understanding slice length and capacity (#20) - 100 Go Mistakes and How to Avoid Them" >
|
||||
|
||||
<meta property="og:description" content="None" >
|
||||
|
||||
<meta property="og:image" content="https://100go.co/assets/images/social/20-slice.png" >
|
||||
|
||||
<meta property="og:image:type" content="image/png" >
|
||||
|
||||
<meta property="og:image:width" content="1200" >
|
||||
|
||||
<meta property="og:image:height" content="630" >
|
||||
|
||||
<meta property="og:url" content="https://100go.co/20-slice/" >
|
||||
|
||||
<meta name="twitter:card" content="summary_large_image" >
|
||||
|
||||
<meta name="twitter:title" content="Not understanding slice length and capacity (#20) - 100 Go Mistakes and How to Avoid Them" >
|
||||
|
||||
<meta name="twitter:description" content="None" >
|
||||
|
||||
<meta name="twitter:image" content="https://100go.co/assets/images/social/20-slice.png" >
|
||||
|
||||
|
||||
|
||||
<link href="../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>
|
||||
html.glightbox-open { overflow: initial; height: 100%; }
|
||||
.gslide-title { margin-top: 0px; user-select: text; }
|
||||
.gslide-desc { color: #666; user-select: text; }
|
||||
.gslide-image img { background: white; }
|
||||
|
||||
.gscrollbar-fixer { padding-right: 15px; }
|
||||
.gdesc-inner { font-size: 0.75rem; }
|
||||
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color);}
|
||||
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color);}
|
||||
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color);}
|
||||
</style> <script src="../assets/javascripts/glightbox.min.js"></script></head>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="cyan" data-md-color-accent="indigo">
|
||||
|
||||
|
||||
|
||||
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
|
||||
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
|
||||
<label class="md-overlay" for="__drawer"></label>
|
||||
<div data-md-component="skip">
|
||||
|
||||
|
||||
<a href="#not-understanding-slice-length-and-capacity" class="md-skip">
|
||||
Skip to content
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<div data-md-component="announce">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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 and How to Avoid Them" class="md-header__button md-logo" aria-label="100 Go Mistakes and How to Avoid Them" data-md-component="logo">
|
||||
|
||||
<img src="../img/Go-Logo_White.svg" alt="logo">
|
||||
|
||||
</a>
|
||||
<label class="md-header__button md-icon" for="__drawer">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
|
||||
</label>
|
||||
<div class="md-header__title" data-md-component="header-title">
|
||||
<div class="md-header__ellipsis">
|
||||
<div class="md-header__topic">
|
||||
<span class="md-ellipsis">
|
||||
100 Go Mistakes and How to Avoid Them
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-header__topic" data-md-component="header-topic">
|
||||
<span class="md-ellipsis">
|
||||
|
||||
Not understanding slice length and capacity (#20)
|
||||
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<form class="md-header__option" data-md-component="palette">
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="cyan" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_1">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_2" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="blue-grey" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_2">
|
||||
|
||||
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12c0-2.42-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69Z"/></svg>
|
||||
</label>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
|
||||
<div class="md-header__option">
|
||||
<div class="md-select">
|
||||
|
||||
<button class="md-header__button md-icon" aria-label="Select language">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="m12.87 15.07-2.54-2.51.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v2h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04M18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12m-2.62 7 1.62-4.33L19.12 17h-3.24Z"/></svg>
|
||||
</button>
|
||||
<div class="md-select__inner">
|
||||
<ul class="md-select__list">
|
||||
|
||||
<li class="md-select__item">
|
||||
<a href="/" hreflang="en" class="md-select__link">
|
||||
English
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="md-select__item">
|
||||
<a href="/zh/" hreflang="zh" class="md-select__link">
|
||||
Chinese (Simplified)
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<label class="md-header__button md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
|
||||
</label>
|
||||
<div class="md-search" data-md-component="search" role="dialog">
|
||||
<label class="md-search__overlay" for="__search"></label>
|
||||
<div class="md-search__inner" role="search">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
|
||||
<label class="md-search__icon md-icon" for="__search">
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
|
||||
</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>
|
||||
<div class="md-search-result" data-md-component="search-result">
|
||||
<div class="md-search-result__meta">
|
||||
Initializing search
|
||||
</div>
|
||||
<ol class="md-search-result__list" role="presentation"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="md-header__source">
|
||||
<a href="https://github.com/teivah/100-go-mistakes" title="Go to repository" class="md-source" data-md-component="source">
|
||||
<div class="md-source__icon md-icon">
|
||||
|
||||
<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">
|
||||
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">
|
||||
|
||||
|
||||
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">
|
||||
|
||||
|
||||
|
||||
|
||||
<main class="md-main" data-md-component="main">
|
||||
<div class="md-main__inner md-grid">
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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 and How to Avoid Them" class="md-nav__button md-logo" aria-label="100 Go Mistakes and How to Avoid Them" data-md-component="logo">
|
||||
|
||||
<img src="../img/Go-Logo_White.svg" alt="logo">
|
||||
|
||||
</a>
|
||||
100 Go Mistakes and How to Avoid Them
|
||||
</label>
|
||||
|
||||
<div class="md-nav__source">
|
||||
<a href="https://github.com/teivah/100-go-mistakes" title="Go to repository" class="md-source" data-md-component="source">
|
||||
<div class="md-source__icon md-icon">
|
||||
|
||||
<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">
|
||||
teivah/100-go-mistakes
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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">
|
||||
100 Go Mistakes and How to Avoid Them
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../chapter-1/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Read the First Chapter
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../external/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
External Resources
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</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" checked>
|
||||
|
||||
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
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>
|
||||
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">
|
||||
Common Go Mistakes
|
||||
</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">
|
||||
Full Sections
|
||||
</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="true">
|
||||
<label class="md-nav__title" for="__nav_2_2">
|
||||
<span class="md-nav__icon md-icon"></span>
|
||||
Full Sections
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../9-generics/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Being confused about when to use generics (#9)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<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">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Maps and memory leaks (#28)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../89-benchmarks/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Writing inaccurate benchmarks (#89)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../98-profiling-execution-tracing/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not using Go diagnostics tooling (#98)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../zh/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Chinese (Simplified) Version
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
|
||||
|
||||
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="md-content" data-md-component="content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h1 id="not-understanding-slice-length-and-capacity">Not understanding slice length and capacity</h1>
|
||||
<p>It’s pretty common for Go developers to mix slice length and capacity or not understand them thoroughly. Assimilating these two concepts is essential for efficiently handling core operations such as slice initialization and adding elements with append, copying, or slicing. This misunderstanding can lead to using slices suboptimally or even to memory leaks.</p>
|
||||
<p>In Go, a slice is backed by an array. That means the slice’s data is stored contiguously in an array data structure. A slice also handles the logic of adding an element if the backing array is full or shrinking the backing array if it’s almost empty.</p>
|
||||
<p>Internally, a slice holds a pointer to the backing array plus a length and a capacity. The length is the number of elements the slice contains, whereas the capacity is the number of elements in the backing array, counting from the first element in the slice. Let’s go through a few examples to make things clearer. First, let’s initialize a slice with a given length and capacity:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nx">s</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">6</span><span class="p">)</span><span class="w"> </span><span class="c1">// Three-length, six-capacity slice</span>
|
||||
</span></code></pre></div>
|
||||
<p>The first argument, representing the length, is mandatory. However, the second argument representing the capacity is optional. Figure 1 shows the result of this code in memory.</p>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-1.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-1.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 1: A three-length, six-capacity slice.</figcaption>
|
||||
</figure>
|
||||
<p>In this case, <code>make</code> creates an array of six elements (the capacity). But because the length was set to 3, Go initializes only the first three elements. Also, because the slice is an <code>[]int</code> type, the first three elements are initialized to the zeroed value of an <code>int</code>: 0. The grayed elements are allocated but not yet used.</p>
|
||||
<p>If we print this slice, we get the elements within the range of the length, <code>[0 0 0]</code>. If we set <code>s[1]</code> to 1, the second element of the slice updates without impacting its length or capacity. Figure 2 illustrates this.</p>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-2.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-2.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 2: Updating the slice’s second element: s[1] = 1.</figcaption>
|
||||
</figure>
|
||||
<p>However, accessing an element outside the length range is forbidden, even though it’s already allocated in memory. For example, <code>s[4]</code> = 0 would lead to the following panic:</p>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a>panic: runtime error: index out of range [4] with length 3
|
||||
</span></code></pre></div>
|
||||
<p>How can we use the remaining space of the slice? By using the <code>append</code> built-in function:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="nx">s</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>This code appends to the existing <code>s</code> slice a new element. It uses the first grayed element (which was allocated but not yet used) to store element 2, as figure 3 shows.</p>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-3.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-3.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 3: Appending an element to s.</figcaption>
|
||||
</figure>
|
||||
<p>The length of the slice is updated from 3 to 4 because the slice now contains four elements. Now, what happens if we add three more elements so that the backing array isn’t large enough?</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="nx">s</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">5</span><span class="p">)</span>
|
||||
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">s</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>If we run this code, we see that the slice was able to cope with our request:</p>
|
||||
<div class="language-text highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a>[0 1 0 2 3 4 5]
|
||||
</span></code></pre></div>
|
||||
<p>Because an array is a fixed-size structure, it can store the new elements until element 4. When we want to insert element 5, the array is already full: Go internally creates another array by doubling the capacity, copying all the elements, and then inserting element 5. Figure 4 shows this process.</p>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-4.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-4.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 4: Because the initial backing array is full, Go creates another array and copies all the elements.</figcaption>
|
||||
</figure>
|
||||
<p>The slice now references the new backing array. What will happen to the previous backing array? If it’s no longer referenced, it’s eventually freed by the garbage collector (GC) if allocated on the heap. (We discuss heap memory in mistake #95, “<a href="https://100go.co#not-understanding-stack-vs-heap-95">Not understanding stack vs. heap</a>,” and we look at how the GC works in mistake #99, “<a href="https://100go.co#not-understanding-how-the-gc-works-99">Not understanding how the GC works</a>.”)</p>
|
||||
<p>What happens with slicing? Slicing is an operation done on an array or a slice, providing a half-open range; the first index is included, whereas the second is excluded. The following example shows the impact, and figure 5 displays the result in memory:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="nx">s1</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">make</span><span class="p">([]</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">6</span><span class="p">)</span><span class="w"> </span><span class="c1">// Three-length, six-capacity slice</span>
|
||||
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="nx">s2</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">s1</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">]</span><span class="w"> </span><span class="c1">// Slicing from indices 1 to 3</span>
|
||||
</span></code></pre></div>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-5.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-5.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 5: The slices s1 and s2 reference the same backing array with different lengths and capacities.</figcaption>
|
||||
</figure>
|
||||
<p>First, <code>s1</code> is created as a three-length, six-capacity slice. When <code>s2</code> is created by slicing <code>s1</code>, both slices reference the same backing array. However, <code>s2</code> starts from a different index, 1. Therefore, its length and capacity (a two-length, five-capacity slice) differ from s1. If we update <code>s1[1]</code> or <code>s2[0]</code>, the change is made to the same array, hence, visible in both slices, as figure 6 shows.</p>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-6.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-6.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 6: Because s1 and s2 are backed by the same array, updating a common element makes the change visible in both slices.</figcaption>
|
||||
</figure>
|
||||
<p>Now, what happens if we append an element to <code>s2</code>? Does the following code change <code>s1</code> as well?</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="nx">s2</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s2</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>The shared backing array is modified, but only the length of <code>s2</code> changes. Figure 7 shows the result of appending an element to <code>s2</code>.</p>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-7.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-7.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 7: Appending an element to s2.</figcaption>
|
||||
</figure>
|
||||
<p><code>s1</code> remains a three-length, six-capacity slice. Therefore, if we print <code>s1</code> and <code>s2</code>, the added element is only visible for <code>s2</code>:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="nx">s1</span><span class="p">=[</span><span class="mi">0</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">0</span><span class="p">],</span><span class="w"> </span><span class="nx">s2</span><span class="p">=[</span><span class="mi">1</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">2</span><span class="p">]</span>
|
||||
</span></code></pre></div>
|
||||
<p>It’s important to understand this behavior so that we don’t make wrong assumptions while using append.</p>
|
||||
<details class="note" open="open">
|
||||
<summary>Note</summary>
|
||||
<p>In these examples, the backing array is internal and not available directly to the Go developer. The only exception is when a slice is created from slicing an existing array.</p>
|
||||
</details>
|
||||
<p>One last thing to note: what if we keep appending elements to <code>s2</code> until the backing array is full? What will the state be, memory-wise? Let’s add three more elements so that the backing array will not have enough capacity:</p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-8-1"><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="nx">s2</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span>
|
||||
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a><span class="nx">s2</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s2</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)</span><span class="w"> </span><span class="c1">// At this stage, the backing is already full</span>
|
||||
</span><span id="__span-8-3"><a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a><span class="nx">s2</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nb">append</span><span class="p">(</span><span class="nx">s2</span><span class="p">,</span><span class="w"> </span><span class="mi">5</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>This code leads to creating another backing array. Figure 8 displays the results in memory.</p>
|
||||
<figure>
|
||||
<p><a class="glightbox" href="../img/slice-8.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="../img/slice-8.png" /></a>
|
||||
</p>
|
||||
<figcaption>Figure 8: Appending elements to s2 until the backing array is full.</figcaption>
|
||||
</figure>
|
||||
<p><code>s1</code> and <code>s2</code> now reference two different arrays. As <code>s1</code> is still a three-length, six-capacity slice, it still has some available buffer, so it keeps referencing the initial array. Also, the new backing array was made by copying the initial one from the first index of <code>s2</code>. That’s why the new array starts with element 1, not 0.</p>
|
||||
<p>To summarize, 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. Adding an element to a full slice (length == capacity) leads to creating a new backing array with a new capacity, copying all the elements from the previous array, and updating the slice pointer to the new array.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</article>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<footer class="md-footer">
|
||||
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-copyright">
|
||||
|
||||
<div class="md-copyright__highlight">
|
||||
Copyright © 2022 - 2023 Teiva Harsanyi
|
||||
</div>
|
||||
|
||||
|
||||
Made with
|
||||
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
|
||||
Material for MkDocs
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="md-social">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="https://twitter.com/teivah" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 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="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a href="http://blog.teivah.io" target="_blank" rel="noopener" title="blog.teivah.io" class="md-social__link">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 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="M180.5 74.262C80.813 74.262 0 155.633 0 256s80.819 181.738 180.5 181.738S361 356.373 361 256 280.191 74.262 180.5 74.262Zm288.25 10.646c-49.845 0-90.245 76.619-90.245 171.095s40.406 171.1 90.251 171.1 90.251-76.619 90.251-171.1H559c0-94.503-40.4-171.095-90.248-171.095Zm139.506 17.821c-17.526 0-31.735 68.628-31.735 153.274s14.2 153.274 31.735 153.274S640 340.631 640 256c0-84.649-14.215-153.271-31.742-153.271Z"/></svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<div class="md-dialog" data-md-component="dialog">
|
||||
<div class="md-dialog__inner md-typeset"></div>
|
||||
</div>
|
||||
|
||||
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "search.highlight", "search.share", "search.suggest", "content.code.copy"], "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>
|
||||
|
||||
|
||||
<script>document$.subscribe(() => {const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});})</script></body>
|
||||
</html>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
<link rel="canonical" href="https://100go.co/28-maps-memory-leaks/">
|
||||
|
||||
|
||||
<link rel="prev" href="../9-generics/">
|
||||
<link rel="prev" href="../20-slice/">
|
||||
|
||||
|
||||
<link rel="next" href="../89-benchmarks/">
|
||||
|
|
@ -607,6 +607,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item md-nav__item--active">
|
||||
|
|
|
|||
|
|
@ -553,6 +553,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="/28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||
|
|
@ -607,6 +607,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
<link rel="prev" href="..">
|
||||
|
||||
|
||||
<link rel="next" href="../28-maps-memory-leaks/">
|
||||
<link rel="next" href="../20-slice/">
|
||||
|
||||
|
||||
<link rel="icon" href="../img/Go-Logo_LightBlue.svg">
|
||||
|
|
@ -668,6 +668,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||
|
|
@ -607,6 +607,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||
BIN
site/assets/images/social/20-slice.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
|
|
@ -671,6 +671,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
@ -917,7 +937,7 @@
|
|||
<li>
|
||||
<p><em>100 Go Mistakes and How to Avoid Them</em> (🇬🇧 edition: paper, digital, or audiobook)</p>
|
||||
<ul>
|
||||
<li><a href="https://www.manning.com/books/100-go-mistakes-and-how-to-avoid-them">Manning</a></li>
|
||||
<li><a href="https://www.manning.com/books/100-go-mistakes-and-how-to-avoid-them">Manning</a> (make sure to use my personal discount code for -35%: <code>au35har</code>)</li>
|
||||
<li><a href="https://www.oreilly.com/library/view/100-go-mistakes/9781617299599/">O’Reilly</a></li>
|
||||
<li>Amazon: <a href="https://www.amazon.com/dp/1617299596">.com</a>, <a href="https://www.amazon.co.uk/dp/B0BBSNJR6B">.co.uk</a>, <a href="https://www.amazon.de/dp/B0BBHQD8BQ">.de</a>, <a href="https://www.amazon.fr/100-Mistakes-How-Avoid-Them/dp/1617299596">.fr</a>, <a href="https://www.amazon.in/dp/B0BBHQD8BQ">.in</a>, <a href="https://www.amazon.co.jp/dp/B0BBHQD8BQ">.co.jp</a>, <a href="https://www.amazon.es/dp/B0BBHQD8BQ">.es</a>, <a href="https://www.amazon.it/dp/B0BBHQD8BQ">.it</a>, <a href="https://www.amazon.com.br/dp/B0BBHQD8BQ">.com.br</a></li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -728,6 +728,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||
20
site/external/index.html
vendored
|
|
@ -673,6 +673,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||
BIN
site/img/slice-1.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
site/img/slice-2.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
site/img/slice-3.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
site/img/slice-4.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
site/img/slice-5.png
Normal file
|
After Width: | Height: | Size: 8 KiB |
BIN
site/img/slice-6.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
site/img/slice-7.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
site/img/slice-8.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
127
site/index.html
|
|
@ -1515,6 +1515,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
@ -2647,10 +2667,12 @@
|
|||
<p>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.</p>
|
||||
</details>
|
||||
<p>An init function is a function used to initialize the state of an application. It takes no arguments and returns no result (a <code>func()</code> function). When a package is initialized, all the constant and variable declarations in the package are evaluated. Then, the init functions are executed.</p>
|
||||
<p>Init functions can lead to some issues:
|
||||
* They can limit error management.
|
||||
* They can complicate how to implement tests (for example, an external dependency must be set up, which may not be necessary for the scope of unit tests).
|
||||
* If the initialization requires us to set a state, that has to be done through global variables.</p>
|
||||
<p>Init functions can lead to some issues:</p>
|
||||
<ul>
|
||||
<li>They can limit error management.</li>
|
||||
<li>They can complicate how to implement tests (for example, an external dependency must be set up, which may not be necessary for the scope of unit tests).</li>
|
||||
<li>If the initialization requires us to set a state, that has to be done through global variables.</li>
|
||||
</ul>
|
||||
<p>We should be cautious with init functions. They can be helpful in some situations, however, such as defining static configuration. Otherwise, and in most cases, we should handle initializations through ad hoc functions.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/3-init-functions/">Source code</a></p>
|
||||
<h3 id="overusing-getters-and-setters-4">Overusing getters and setters (#4)</h3>
|
||||
|
|
@ -2724,9 +2746,11 @@ What’s the main problem if we overuse interfaces? The answer is that they make
|
|||
<p>We use embedding to promote the fields and methods of an embedded type. Because Bar contains a Baz field, this field is
|
||||
promoted to <code>Foo</code>. Therefore, Baz becomes available from Foo.</p>
|
||||
<p>What can we say about type embedding? First, let’s note that it’s rarely a necessity, and it means that whatever the use case, we can probably solve it as well without type embedding. Type embedding is mainly used for convenience: in most cases, to promote behaviors.</p>
|
||||
<p>If we decide to use type embedding, we need to keep two main constraints in mind:
|
||||
* It shouldn’t be used solely as some syntactic sugar to simplify accessing a field (such as <code>Foo.Baz()</code> instead of <code>Foo.Bar.Baz()</code>). If this is the only rationale, let’s not embed the inner type and use a field instead.
|
||||
* It shouldn’t promote data (fields) or a behavior (methods) we want to hide from the outside: for example, if it allows clients to access a locking behavior that should remain private to the struct.</p>
|
||||
<p>If we decide to use type embedding, we need to keep two main constraints in mind:</p>
|
||||
<ul>
|
||||
<li>It shouldn’t be used solely as some syntactic sugar to simplify accessing a field (such as <code>Foo.Baz()</code> instead of <code>Foo.Bar.Baz()</code>). If this is the only rationale, let’s not embed the inner type and use a field instead.</li>
|
||||
<li>It shouldn’t promote data (fields) or a behavior (methods) we want to hide from the outside: for example, if it allows clients to access a locking behavior that should remain private to the struct.</li>
|
||||
</ul>
|
||||
<p>Using type embedding consciously by keeping these constraints in mind can help avoid boilerplate code with additional forwarding methods. However, let’s make sure we don’t do it solely for cosmetics and not promote elements that should remain hidden.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/02-code-project-organization/10-type-embedding/main.go">Source code</a></p>
|
||||
<h3 id="not-using-the-functional-options-pattern-11">Not using the functional options pattern (#11)</h3>
|
||||
|
|
@ -2734,9 +2758,11 @@ promoted to <code>Foo</code>. Therefore, Baz becomes available from Foo.</p>
|
|||
<summary>TL;DR</summary>
|
||||
<p>To handle options conveniently and in an API-friendly manner, use the functional options pattern.</p>
|
||||
</details>
|
||||
<p>Although there are different implementations with minor variations, the main idea is as follows:
|
||||
* An unexported struct holds the configuration: options.
|
||||
* Each option is a function that returns the same type: <code>type Option func(options *options)</code> error. For example, <code>WithPort</code> accepts an <code>int</code> argument that represents the port and returns an <code>Option</code> type that represents how to update the <code>options</code> struct.</p>
|
||||
<p>Although there are different implementations with minor variations, the main idea is as follows:</p>
|
||||
<ul>
|
||||
<li>An unexported struct holds the configuration: options.</li>
|
||||
<li>Each option is a function that returns the same type: <code>type Option func(options *options)</code> error. For example, <code>WithPort</code> accepts an <code>int</code> argument that represents the port and returns an <code>Option</code> type that represents how to update the <code>options</code> struct.</li>
|
||||
</ul>
|
||||
<p><a class="glightbox" href="img/options.png" data-type="image" data-width="100%" data-height="auto" data-desc-position="bottom"><img alt="" src="img/options.png" /></a></p>
|
||||
<div class="language-go highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="kd">type</span><span class="w"> </span><span class="nx">options</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span>
|
||||
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="w"> </span><span class="nx">port</span><span class="w"> </span><span class="o">*</span><span class="kt">int</span>
|
||||
|
|
@ -2822,29 +2848,33 @@ Granularity is another essential thing to consider. We should avoid having dozen
|
|||
<p>To improve code quality and consistency, use linters and formatters.</p>
|
||||
</details>
|
||||
<p>A linter is an automatic tool to analyze code and catch errors. The scope of this section isn’t 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.</p>
|
||||
<p>However, if you’re not a regular user of linters, here is a list that you may want to use daily:
|
||||
* https://golang.org/cmd/vet/—A standard Go analyzer
|
||||
* https://github.com/kisielk/errcheck—An error checker
|
||||
* https://github.com/fzipp/gocyclo—A cyclomatic complexity analyzer
|
||||
* https://github.com/jgautheron/goconst—A repeated string constants analyzer
|
||||
<p>However, if you’re not a regular user of linters, here is a list that you may want to use daily:</p>
|
||||
<ul>
|
||||
<li><a href="https://golang.org/cmd/vet">https://golang.org/cmd/vet</a>—A standard Go analyzer</li>
|
||||
<li><a href="https://github.com/kisielk/errcheck">https://github.com/kisielk/errcheck</a>—An error checker</li>
|
||||
<li><a href="https://github.com/fzipp/gocyclo">https://github.com/fzipp/gocyclo</a>—A cyclomatic complexity analyzer</li>
|
||||
<li><a href="https://github.com/jgautheron/goconst">https://github.com/jgautheron/goconst</a>—A repeated string constants analyzer
|
||||
*
|
||||
Besides linters, we should also use code formatters to fix code style. Here is a list of some code formatters for you to try:
|
||||
* https://golang.org/cmd/gofmt/—A standard Go code formatter
|
||||
* https://godoc.org/golang.org/x/tools/cmd/goimports—A standard Go imports formatter
|
||||
Besides linters, we should also use code formatters to fix code style. Here is a list of some code formatters for you to try:</li>
|
||||
<li><a href="https://golang.org/cmd/gofmt">https://golang.org/cmd/gofmt</a>—A standard Go code formatter</li>
|
||||
<li><a href="https://godoc.org/golang.org/x/tools/cmd/goimports">https://godoc.org/golang.org/x/tools/cmd/goimports</a>—A standard Go imports formatter
|
||||
*
|
||||
Meanwhile, we should also look at golangci-lint (https://github.com/golangci/ golangci-lint). It’s a linting tool that provides a facade on top of many useful linters and formatters. Also, it allows running the linters in parallel to improve analysis speed, which is quite handy.</p>
|
||||
Meanwhile, we should also look at golangci-lint (<a href="https://github.com/golangci/golangci-lint">https://github.com/golangci/golangci-lint</a>). It’s a linting tool that provides a facade on top of many useful linters and formatters. Also, it allows running the linters in parallel to improve analysis speed, which is quite handy.</li>
|
||||
</ul>
|
||||
<p>Linters and formatters are a powerful way to improve the quality and consistency of our codebase. Let’s take the time to understand which one we should use and make sure we automate their execution (such as a CI or Git precommit hook).</p>
|
||||
<h2 id="data-types">Data Types</h2>
|
||||
<h3 id="creating-confusion-with-octal-literals-17">Creating confusion with octal literals (#17)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>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 <code>0o</code>.</p>
|
||||
<p>When reading existing code, bear in mind that integer literals starting with <code>0</code> are octal numbers. Also, to improve readability, make octal integers explicit by prefixing them with <code>0o</code>.</p>
|
||||
</details>
|
||||
<p>Octal numbers start with a 0 (e.g., <code>010</code> 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 <code>0o</code> prefix (e.g., <code>0o10</code>).</p>
|
||||
<p>We should also note the other integer literal representations:
|
||||
* <em>Binary</em>—Uses a <code>0b</code> or <code>0B</code> prefix (for example, <code>0b100</code> is equal to 4 in base 10)
|
||||
* <em>Hexadecimal</em>—Uses an <code>0x</code> or <code>0X</code> prefix (for example, <code>0xF</code> is equal to 15 in base 10)
|
||||
* <em>Imaginary</em>—Uses an <code>i</code> suffix (for example, <code>3i</code>)</p>
|
||||
<p>We should also note the other integer literal representations:</p>
|
||||
<ul>
|
||||
<li><em>Binary</em>—Uses a <code>0b</code> or <code>0B</code> prefix (for example, <code>0b100</code> is equal to 4 in base 10)</li>
|
||||
<li><em>Hexadecimal</em>—Uses an <code>0x</code> or <code>0X</code> prefix (for example, <code>0xF</code> is equal to 15 in base 10)</li>
|
||||
<li><em>Imaginary</em>—Uses an <code>i</code> suffix (for example, <code>3i</code>)</li>
|
||||
</ul>
|
||||
<p>We can also use an underscore character (_) as a separator for readability. For example, we can write 1 billion this way: <code>1_000_000_000</code>. We can also use the underscore character with other representations (for example, <code>0b00_00_01</code>).</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/17-octal-literals/main.go">Source code</a></p>
|
||||
<h3 id="neglecting-integer-overflows-18">Neglecting integer overflows (#18)</h3>
|
||||
|
|
@ -2870,18 +2900,19 @@ Meanwhile, we should also look at golangci-lint (https://github.com/golangci/ go
|
|||
</span><span id="__span-8-2"><a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a><span class="nx">fmt</span><span class="p">.</span><span class="nx">Println</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span>
|
||||
</span></code></pre></div>
|
||||
<p>We may expect this code to print the result of 1.0001 * 1.0001 = 1.00020001, right? However, running it on most x86 processors prints 1.0002, instead.</p>
|
||||
<p>Because Go’s <code>float32</code> and <code>float64</code> types are approximations, we have to bear a few rules in mind:
|
||||
* When comparing two floating-point numbers, check that their difference is within an acceptable range.
|
||||
* When performing additions or subtractions, group operations with a similar order of magnitude for better accuracy.
|
||||
* To favor accuracy, if a sequence of operations requires addition, subtraction, multiplication, or division, perform the multiplication and division operations first.</p>
|
||||
<p>Because Go’s <code>float32</code> and <code>float64</code> types are approximations, we have to bear a few rules in mind:</p>
|
||||
<ul>
|
||||
<li>When comparing two floating-point numbers, check that their difference is within an acceptable range.</li>
|
||||
<li>When performing additions or subtractions, group operations with a similar order of magnitude for better accuracy.</li>
|
||||
<li>To favor accuracy, if a sequence of operations requires addition, subtraction, multiplication, or division, perform the multiplication and division operations first.</li>
|
||||
</ul>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/19-floating-points/main.go">Source code</a></p>
|
||||
<h3 id="not-understanding-slice-length-and-capacity-20">Not understanding slice length and capacity (#20)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Understanding the difference between slice length and capacity should be part of a Go developer’s core knowledge. The slice length is the number of available elements in the slice, whereas the slice capacity is the number of elements in the backing array.</p>
|
||||
</details>
|
||||
<!-- TODO -->
|
||||
|
||||
<p>Read the full section <a href="20-slice/">here</a>.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/03-data-types/20-slice-length-cap/main.go">Source code</a></p>
|
||||
<h3 id="inefficient-slice-initialization-21">Inefficient slice initialization (#21)</h3>
|
||||
<details class="info" open="open">
|
||||
|
|
@ -2961,14 +2992,16 @@ Meanwhile, we should also look at golangci-lint (https://github.com/golangci/ go
|
|||
<summary>TL;DR</summary>
|
||||
<p>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 <code>reflect.DeepEqual</code> and pay the price of reflection or use custom implementations and libraries.</p>
|
||||
</details>
|
||||
<p>It’s essential to understand how to use <code>==</code> and <code>!=</code> to make comparisons effectively. We can use these operators on operands that are comparable:
|
||||
* <em>Booleans</em>—Compare whether two Booleans are equal.
|
||||
* <em>Numerics (int, float, and complex types)</em>—Compare whether two numerics are equal.
|
||||
* <em>Strings</em>—Compare whether two strings are equal.
|
||||
* <em>Channels</em>—Compare whether two channels were created by the same call to make or if both are nil.
|
||||
* <em>Interfaces</em>—Compare whether two interfaces have identical dynamic types and equal dynamic values or if both are nil.
|
||||
* <em>Pointers</em>—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.</p>
|
||||
<p>It’s essential to understand how to use <code>==</code> and <code>!=</code> to make comparisons effectively. We can use these operators on operands that are comparable:</p>
|
||||
<ul>
|
||||
<li><em>Booleans</em>—Compare whether two Booleans are equal.</li>
|
||||
<li><em>Numerics (int, float, and complex types)</em>—Compare whether two numerics are equal.</li>
|
||||
<li><em>Strings</em>—Compare whether two strings are equal.</li>
|
||||
<li><em>Channels</em>—Compare whether two channels were created by the same call to make or if both are nil.</li>
|
||||
<li><em>Interfaces</em>—Compare whether two interfaces have identical dynamic types and equal dynamic values or if both are nil.</li>
|
||||
<li><em>Pointers</em>—Compare whether two pointers point to the same value in memory or if both are nil.</li>
|
||||
<li>_Structs and arrays)—Compare whether they are composed of similar types.</li>
|
||||
</ul>
|
||||
<details class="note" open="open">
|
||||
<summary>Note</summary>
|
||||
<p>We can also use the <code>?</code>, <code>>=</code>, <code><</code>, and <code>></code> operators with numeric types to compare values and with strings to compare their lexical order.</p>
|
||||
|
|
@ -2983,13 +3016,15 @@ One additional note: we must remember that the standard library has some existin
|
|||
<summary>TL;DR</summary>
|
||||
<p>The value element in a <code>range</code> loop is a copy. Therefore, to mutate a struct, for example, access it via its index or via a classic <code>for</code> loop (unless the element or the field you want to modify is a pointer).</p>
|
||||
</details>
|
||||
<p>A range loop allows iterating over different data structures:
|
||||
* String
|
||||
* Array
|
||||
* Pointer to an array
|
||||
* Slice
|
||||
* Map
|
||||
* Receiving channel</p>
|
||||
<p>A range loop allows iterating over different data structures:</p>
|
||||
<ul>
|
||||
<li>String</li>
|
||||
<li>Array</li>
|
||||
<li>Pointer to an array</li>
|
||||
<li>Slice</li>
|
||||
<li>Map</li>
|
||||
<li>Receiving channel</li>
|
||||
</ul>
|
||||
<p>Compared to a classic for <code>loop</code>, a <code>range</code> loop is a convenient way to iterate over all the elements of one of these data structures, thanks to its concise syntax.</p>
|
||||
<p>Yet, we should remember that the value element in a range loop is a copy. Therefore, if the value is a struct we need to mutate, we will only update the copy, not the element itself, unless the value or field we modify is a pointer. The favored options are to access the element via the index using a range loop or a classic for loop.</p>
|
||||
<p><a href="https://github.com/teivah/100-go-mistakes/tree/master/src/04-control-structures/30-range-loop-element-copied/">Source code</a></p>
|
||||
|
|
@ -3851,7 +3886,7 @@ One additional note: we must remember that the standard library has some existin
|
|||
<summary>TL;DR</summary>
|
||||
<p>Use the fast-path inlining technique to efficiently reduce the amortized time to call a function.</p>
|
||||
</details>
|
||||
<h3 id="not-using-go-diagnostics-tooling-98"><a href="https://medium.com/@teivah/profiling-and-execution-tracing-in-go-a5e646970f5b">Not using Go diagnostics tooling</a> (#98)</h3>
|
||||
<h3 id="not-using-go-diagnostics-tooling-98">Not using Go diagnostics tooling (#98)</h3>
|
||||
<details class="info" open="open">
|
||||
<summary>TL;DR</summary>
|
||||
<p>Rely on profiling and the execution tracer to understand how an application performs and the parts to optimize.</p>
|
||||
|
|
|
|||
|
|
@ -603,6 +603,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||
|
|
@ -2,52 +2,57 @@
|
|||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://100go.co/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/20-slice/</loc>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/28-maps-memory-leaks/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/89-benchmarks/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/9-generics/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/98-profiling-execution-tracing/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/book/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/chapter-1/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/external/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/jobs/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://100go.co/zh/</loc>
|
||||
<lastmod>2023-09-17</lastmod>
|
||||
<lastmod>2023-09-18</lastmod>
|
||||
<changefreq>daily</changefreq>
|
||||
</url>
|
||||
</urlset>
|
||||
|
|
@ -605,6 +605,26 @@
|
|||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../20-slice/" class="md-nav__link">
|
||||
|
||||
|
||||
<span class="md-ellipsis">
|
||||
Not understanding slice length and capacity (#20)
|
||||
</span>
|
||||
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<li class="md-nav__item">
|
||||
<a href="../28-maps-memory-leaks/" class="md-nav__link">
|
||||
|
||||
|
|
|
|||