interview questions
Recently, the author of Go 101 released 11 Go interview questions, which are very interesting. I plan to write a series to analyze each question in detail. Welcome everyone to pay attention.
This question is the second question in the Go quiz slice
series, which is very confusing.
Through this question, we can know the slice
so as to avoid stepping on pits in actual projects.
package main
func main() {
var x = []string{"A", "B", "C"}
for i, s := range x {
print(i, s, ",")
x[i+1] = "M"
x = append(x, "Z")
x[i+1] = "Z"
}
}
- 0A,1B,2C,
- 0A,1Z,2Z,
- 0A,1M,2M,
- 0A,1M,2C,
- 0A,1Z,2M,
- 0A,1M,2Z,
- (infinite loop)
You can leave your answers in the comments section. This question has the following main points:
slice
does range traversal, what does the Go compiler do behind the scenes?slice
be expanded, and what is the behavior after expansion?
Parse
Let us answer the above questions one by one.
range traversal mechanism
When range slice
, it actually constructs a copy of the original slice first, and then traverses the copy.
This copied value is determined before the logic inside the for loop is executed. Therefore, the length and capacity of this copy will not change during the for loop.
Take the above topic as an example: range x
actually construct a x
, we assume it is y
, and then traverse y
for i, s := range x {
print(i, s, ",")
x[i+1] = "M"
x = append(x, "Z")
x[i+1] = "Z"
}
The above code can be equivalent to:
y := x
for i := 0; i < len(y); i++ {
print(i, y[i], ",")
x[i+1] = "M"
x = append(x, "Z")
x[i+1] = "Z"
}
Slice expansion mechanism
slice
adding elements to 061f35c390ad43 through the append
function, there are two situations:
- If the capacity of the slice is sufficient, the element is appended to the underlying array pointed to by the slice.
- If the capacity of the slice is not enough to carry the newly added elements, a new underlying array will be opened, the elements in the original slice will be copied, and new elements will be added. The pointers in the slice structure will point to the new underlying array.
Answer
Let's go back to the topic at the beginning of this article and parse the execution result of each line of code line by line.
code | program execution result |
---|---|
var x = []string{"A", "B", "C"} | x is a slice with a length of 3 and a capacity of 3. The value of the underlying array pointed to by x is [ "A" "B" "C"] |
for i, s := range x | A compiler configured to slice x copy assumed slices y , then y do traversal. y is determined before the for loop is executed. The length is 3 and the capacity is 3, which is fixed. |
print(i, s, ",") | The first for loop, i value is 0, s values are slice y where the subscript index a 0 element, the value "A", print 0A |
x[i+1] = "M" | Execute x[1] = "M", because slices x and y now point to the same underlying array, the value of the element with subscript index 1 in y is also changed to "M", and the value of the underlying array pointed to by y is ["A", "M", "C"] |
x = append(x, "Z") | To slice x add a new element "Z", because the current slice x lengths of 3, 3 capacity, the capacity is full, the newly added elements of the carrier is insufficient, so on x make expansion of the underlying array, x point to the new bottom Array, the value of the new underlying array is ["A", "M", "C", "Z"], y still points to the original underlying array, and the value of the underlying array pointed to by y , "C"] |
subsequent for loop | Because starting from the second for loop, x and y point to different underlying arrays, so x will not affect y , so the results printed later are 1M, 2C in turn |
So the answer to this question is 0A, 1M, 2C.
Summarize
For the slice, I always think about how the three fields in the slice: pointer, length, and capacity have changed after the slice has been modified.
zen of go
- Sections
x
do traverse range, it is actuallyx
copies (assumingy
) do traverse range,y
value (includingy
value points to the underlying structure in the array of pointers,y
length and capacity) are performedfor
Determined before the cycle. - If you are unclear about the underlying data structure and expansion mechanism of refer to my 161f35c390affc Slice underlying principle chapter , which contains all the precautions for slices.
open source address
The open source address of the article and sample code is on GitHub: https://github.com/jincheng9/go-tutorial
Official account: coding advanced
Personal website: https://jincheng9.github.io/
thinking questions
Leave 2 thinking questions, everyone is welcome to leave your answers in the comment area. You can also message slice2
on my wx account for the answer and reason.
Topic 1:
package main func main() { var x = []string{"A", "B", "C"} for i, s := range x { print(i, s, " ") x = append(x, "Z") x[i+1] = "Z" } }
Topic 2
package main func main() { var y = []string{"A", "B", "C", "D"} var x = y[:3] for i, s := range x { print(i, s, ",") x = append(x, "Z") x[i+1] = "Z" } }
References
- https://go101.org/quizzes/slice-2.html
- https://mp.weixin.qq.com/s?__biz=Mzg2MTcwNjc1Mg==&mid=2247483741&idx=1&sn=486066a3a582faf457f91b8397178f64&chksm=ce124e32f965c72411e2f083c22531aa70bb7fa0946c505dc886fb054b2a644abde3ad7ea6a0&token=609026015&lang=zh_CN#rd
- https://jincheng9.github.io/post/go-slice-principle/
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。