golang array and slice Detailed

First, the array

An array is a sequence of fixed length and the elements of the same type, may consist of an array of zero or more elements.

Each element of the array can be accessed by the index mark, the index of the target range is from zero to an array length minus 1 position. Built-in len function returns the number of elements in the array.

By default, each element of the array are initialized to zero value corresponding to the type of element, for it is the integer 0.

var arr [3]int             // 声明一个长度为3的整型数组
fmt.Println(arr[0])        // 打印第一个元素
fmt.Println(arr[len(arr)-1]) // 打印最后一个元素

// 打印数组的下标和对应的元素
for i, v := range arr {
    fmt.Printf("%d %d\n", i, v)
}

Array may be used with a set of grammatical literal value to initialize the array:

var q [3]int = [3]int{1, 2, 3}
var r [3]int = [3]int{1, 2}     // r[2] == 0

The length of the array must EDITORIAL generally square brackets, if you want to automatically calculate the length of the initial number of elements can be written in square brackets "...", as follows:

q := [...]int{1, 2, 3}
fmt.Printf("%T\n", q) // "[3]int"

Length of the array is an integral part of the array type, so [3] int and [4] int are two different types of arrays. Length of the array must be a constant expression, because the length of the array is determined at compile time.

q := [3]int{1, 2, 3}
q = [4]int{1, 2, 3, 4} // 编译错误!不能将长度为4的数组赋值给长度为3的数组

The above initialization sequence directly form a sequence of values, but can also specify a list of values ​​and the corresponding index mode initialization, as follows:

arr := [...]string{0:"星期天", 1:"星期一", 2:"星期二"}

In literal form of such an array, the index of the initialization sequence is not critical, but the index may omit useless, and rules as mentioned earlier, elements of the initial value is not specified initialized with zero values. E.g,

r := [...]int{99: -1}

R a defined array comprising 100 elements, the last element is initialized to -1, the other elements are initialized with zeros.

We can directly through the == comparison operator to compare two arrays, only when all the elements of the two arrays are equal when the array is equal. Not equal comparison operator! = Follow the same rules.

a := [2]int{1, 2}
b := [...]int{1, 2}
c := [2]int{1, 3}
fmt.Println(a == b, a == c, b == c) // "true false false"
d := [3]int{1, 2}
fmt.Println(a == d) // 编译错误!数组长度不同,不能比较

Function parameter passing mechanism leading to the transfer of a large array type would be inefficient, and any changes to the array parameter are occurring on an array replication, and can not directly modify the original array variable when calling. In this regard, Go language and the way to treat an array of many other programming languages, other programming languages ​​may be implicitly array as a reference or pointer to the object passed to the function is called.

Of course, we can explicitly pass an array of pointers, in that case refers to a function by the array for any modifications can be fed back directly to the caller. The following function is used to [32] is cleared byte array type:

func zero(ptr *[32]byte) {
    for i := range ptr {
        ptr[i] = 0
    }
}

In fact, an array literal [32] byte {} may generate a 32-byte array. And each array element is initialized to zero value, which is zero. Above zero function can be written in a little more succinct:

func zero(ptr *[32]byte) {
    *ptr = [32]byte{}
}

While the parameters to pass a pointer array is highly efficient, and also allows to modify the value of the array within the function, but is still rigid array type, since the type comprising an array of rigid length information. The above function and does not receive zero point [16] pointer byte array type, and there is no way to add or remove the array elements. For these reasons, we generally use the slice instead of an array.

Two, Slice

Slice (Slice) represent variable-length sequences, each sequence element has the same type. Usually writing a slice type [] T, where T represents the type of slice elements; and array slice syntax like, but it is not a fixed length.

Between the array and slice closely linked, slice provides access to an array of sub-sequences (or all) of the functional elements, but does reference the underlying slice of an array object. A slice consists of three parts: the pointer, length and capacity. Pointer to the address of the first element corresponding to a slice of the underlying array element, to be noted that the first element of the first slice is not necessarily element array. Length corresponds to the number of elements in the slice; length can not exceed the capacity, the capacity is typically an end position from the start position of the slice to the underlying data. Built-in functions return len and cap length and volume slice.

The underlying data can be shared among a plurality of slice, and the reference range may overlap portions of the array. The following figure shows an array of strings representing the year the name of each month, as well as references to the two overlapping slice of the array. Such an array of definitions

months := [...]string{1: "January", /* ... */, 12: "December"}

So January is months [1], December is the months [12]. Typically, the first element of the array starting at index 0, but is generally from 1 month to start, so we skip the 0th element of the array at declaration, the 0th element will be automatically initialized to an empty string.

slicing the slice s [i: j], where 0 ≤ i≤ j≤ cap (s), for creating a new slice, a reference sequence s from the beginning of the i-th element to the j-1 th elements . The new slice will only ji elements. If the index i is omitted, the position will be used instead of 0, if the position of the index j is omitted, the use len (s) in place. Thus, months [1:13] effective slicing operation refers to the full month, and months [1:] operation is equivalent; months [:] The slicing operation is to refer to the entire array. Let us define the second quarter and represents a slice of the month northern summer, they have overlapping parts:
Here Insert Picture Description

Q2 := months[4:7]
summer := months[6:9]
fmt.Println(Q2)     // ["April" "May" "June"]
fmt.Println(summer) // ["June" "July" "August"]

If the slicing operation exceeds the cap (s) the upper limit will result in a panic exception, but beyond len (s) is extended slice means, since the new slice length becomes larger:

fmt.Println(summer[:20]) // panic异常:超出范围
endlessSummer := summer[:5] // 长度没有超过容量,可以扩展
fmt.Println(endlessSummer)  // "[June July August September October]"

Further, the slicing operation and the string [] byte byte type slice slicing operation is similar. Writing all x [m: n], and returns the underlying array is a sub-sequence of the original previous series of bytes, we are sharing the bottom, so this is a constant time operation. x [m: n] for slicing string generating a new string, if x is [] byte, to generate a new a [] byte.

Because the slice value contains a pointer to the first element of the slice, the slice is transmitted to a function therefore allows modification of the underlying array element within the function. In other words, just copy a slice of the underlying array to create a new slice alias. The following reverse function [] int type slice inversion in the original memory space, and it can be used for any length slice.

// 将一个任意长度的slice里的元素翻转
func reverse(s []int) {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
}

It is noted that differences in the variable s and the slice type of array type variable initialization of a syntax. Literals and array slice syntax is very similar, they are used to initialize bracket contains a series of elements, but for the slice does not specify the length of the sequence. This implicitly creates an array of suitable size and then slice pointer to the underlying array. Like array literal, slice the literal value can also be specified sequence initialization sequence, or specified by the index and the element value, or a mixture of two styles initialization syntax.

And the array is different, it can not be compared between the slice, so we can not use == slice operator to determine whether it contains two elements are all equal. However, the standard library provides highly optimized bytes.Equal function to determine whether two byte slice is equal to ([] byte), but for other types of slice, we must begin to compare themselves to each element:

func equal(x, y []string) bool {
    if len(x) != len(y) {
        return false
    }
    for i := range x {
        if x[i] != y[i] {
            return false
        }
    }
    return true
}

slice the only legitimate comparison operation is nil and compare, for example:

if summer == nil { /* ... */ }

a slice is equal to a value of zero nil. A slice nil value and not the underlying array. a nil value of the slice length is 0 and capacity, but also the length and capacity of the non-nil values ​​of slice 0 are, for example, [] int {} or make ([] int, 3) [3:]. As with any type of nil value, we can use [] int (nil) type conversion expressions to generate a slice type of a corresponding nil value.

var s []int    // len(s) == 0, s == nil
s = nil        // len(s) == 0, s == nil
s = []int(nil) // len(s) == 0, s == nil
s = []int{}    // len(s) == 0, s != nil

If you need to test whether a slice is empty, use len (s) == 0 to determine, it should not be judged by s == nil. In addition to comparing the outer and equal nil, slice a nil value of the behavior and any other slice of the same length 0; e.g. Reverse (nil) is safe. Except where the document has been explicitly stated, all of the Go language function should be treated in the same way and slice slice zero length nil value.

Built-in functions to create a slice make element type, and capacity specified length. Capacity portion may be omitted, in which case, the capacity will be equal to the length.

make([]T, len)  // 容量等于长度
make([]T, len, cap) // 相当于 make([]T, cap)[:len]

At the bottom, make creating an anonymous array variable, and then returns a slice; only a reference to the underlying array variable anonymously by returning to a slice. In the first statement, slice is a view of the entire array. In the second statement, slice only refers to the first len ​​elements underlying array, but the capacity will contain a whole array. Additional elements are reserved for future growth with.

Built-in functions used to slice append additional elements:

var runes []rune
for _, r := range "Hello, 世界" {
    runes = append(runes, r)
}
fmt.Printf("%q\n", runes) // "['H' 'e' 'l' 'l' 'o' ',' ' ' '世' '界']"

Construction of a slice consisting of nine rune characters using the append function in a loop, of course, correspond to this particular problem we may be built through the Go language [] rune ( "Hello, world") conversion is complete.

Usually we do not know whether to call append led to a re-allocation of memory, so we can not confirm that the new slice and whether the original slice refer to the same underlying array space. Similarly, we can not confirm whether the operation on the original slice will affect the new slice. Therefore, usually the result of the assignment append returned directly to slice the input variables:

runes = append(runes, r)

Built-in functions can be added to append multiple elements, even append a slice.

var x []int
x = append(x, 1)
x = append(x, 2, 3)
x = append(x, 4, 5, 6)
x = append(x, x...) // append the slice x
fmt.Println(x)      // "[1 2 3 4 5 6 1 2 3 4 5 6]"

Built-in functions can be easily copy a copy another slice to slice the same type. The first parameter is a function to copy copy target slice, the second argument is the source slice, the position and order of the target and source dst = src assignment statement are the same. Two slice may share the same underlying array, there is no problem even overlap. copy function will return the number of successfully copied elements (not used here), equal to two that a smaller slice of length, so we will not worry about beyond the scope of coverage of the target slice.

	dst := []int{1,2,3,4,5}
	src := []int{6,7,8,9,10,11}
	fmt.Println(copy(dst,src))  // 5
	fmt.Println(dst)  // [6 7 8 9 10]
	fmt.Println(src) // [6 7 8 9 10 11]

What questions please leave a message comments area to explore together!

Released four original articles · won praise 0 · Views 65

Guess you like

Origin blog.csdn.net/forjie_/article/details/103899181