1
头图

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:

  1. slice does range traversal, what does the Go compiler do behind the scenes?
  2. 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.

codeprogram 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 xA 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 loopBecause 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 actually x copies (assuming y ) do traverse range, y value (including y value points to the underlying structure in the array of pointers, y length and capacity) are performed for 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


coding进阶
116 声望18 粉丝