go 切片

切片定义

切片是基于数组类型做的一层封装。它非常灵活,可以自动扩容。

var a []int
//定义一个int类型的空切片

切片初始化, a[start:end]创建一个包括从start到end-1的切片。

package main
import ( 
    "fmt"
)
func main() { 
    a := [5]int{76, 77, 78, 79, 80}
    var b []int = a[1:4] //基于数组a创建⼀个切⽚,包括元素a[1] a[2] a[3]
    fmt.Println(b)
}

切片初始化方法2

package main
import ( 
  "fmt"
)
func main() { 
  c := []int{6, 7, 8} //创建⼀个数组并返回⼀个切⽚
  fmt.Println(c)
}

数组切片的基本操作

切片基本操作
a) arr[start:end]:包括start到end-1(包括end-1)之间的所有元素
b) arr[start:]:包括start到arr最后一个元素(包括最后一个元素)之间的所有元素
c) arr[:end]:包括0到end-1(包括end-1)之间的所有元素
d) arr[:]:包括整个数组的所有元素

package main

import (
    "fmt"
)

func testSlice0() {
    var a []int
    if a == nil {
        fmt.Printf("a is nil
")
    } else {
        fmt.Printf("a = %v
", a)
    }
    a[0] = 100
}

func testSlice1() {
    a := [5]int{1, 2, 3, 4, 5}
    var b []int
    b = a[1:4]
    fmt.Printf("slice b:%v
", b)
    fmt.Printf("b[0]=%d
", b[0])
    fmt.Printf("b[1]=%d
", b[1])
    fmt.Printf("b[2]=%d
", b[2])
    fmt.Printf("b[3]=%d
", b[3])
}

func testSlice2() {
    a := []int{1, 2, 3, 4, 5}

    fmt.Printf("slice a:%v type of a:%T
", a, a)
}

func testSlice3() {
    a := [5]int{1, 2, 3, 4, 5}
    var b []int
    b = a[1:4]
    fmt.Printf("slice b:%v
", b)

    // c := a[1:len(a)]
    c := a[1:]
    fmt.Printf("slice c:%v
", c)
    //d := a[0:3]
    d := a[:3]
    fmt.Printf("slice d:%v
", d)
    // e  := a[0:len(a)]
    e := a[:]
    fmt.Printf("slice e:%v
", e)
}

func testSlice4() {
    a := [...]int{1, 2, 3, 4, 5, 7, 8, 9, 11}

    fmt.Printf("array a:%v type of a:%T
", a, a)
    b := a[2:5]
    fmt.Printf("slice b:%v type of b:%T
", b, b)
    /*
        b[0] = b[0] + 10
        b[1] = b[1] + 20
        b[2] = b[2] + 30
    */
    /*
        for index, val := range b {
            fmt.Printf("b[%d]=%d
", index, val)
        }
    */
    for index := range b {
        b[index] = b[index] + 10
    }
    fmt.Printf("after modify slice b, array a:%v type of a:%T
", a, a)
}

func testSlice5() {
    a := [...]int{1, 2, 3}
    s1 := a[:]
    s2 := a[:]
    s1[0] = 100
    fmt.Printf("a=%v s2=%v
", a, s2)
    s2[1] = 200
    fmt.Printf("a=%v s1=%v
", a, s1)
}

func main() {
    //testSlice0()
    //testSlice1()
    //testSlice2()
    //testSlice3()
    //testSlice4()
    testSlice5()
}
test

切片修改

package main
import ( 
 "fmt"
)
func main() { 
 //创建一个数组,其中[…]是编译器确定数组的⻓度,darr的长度是9
 darr := [...]int{57, 89, 90, 82, 100, 78, 67, 69, 59}
 //基于darr创建一个切片dslice,包括darr[2],darr[3],darr[4]三个元素
 dslice := darr[2:5]
 fmt.Println("array before",darr)
 for i := range dslice {
 //对于dslice中每个元素进行+1,其实修改是darr[2],darr[3],darr[4]
 dslice[i]++
 }
 fmt.Println("array after",darr)
}
package main
import ( 
 "fmt"
)
func main() { 
 numa := [3]int{78, 79 ,80}
 //创建一个切片,包含整个数组的所有元素
 nums1 := numa[:]
 nums2 := numa[:]
 fmt.Println("array before change 1",numa)
 nums1[0] = 100
 fmt.Println("array after modification to slice nums1", numa)
 nums2[1] = 101
 fmt.Println("array after modification to slice nums2", numa)
}

使用make创建切片

package main
import ( 
    "fmt"
)
func main() { 
    //[]中没有长度
    i := make([]int, 5, 5)
    fmt.Println(i)
}

切片的长度和容量

package main
import ( 
    "fmt"
)
func main() { 
    fruitarray := […]string{
        "apple", "orange", "grape",
        "mango", "water melon",
        "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    //长度是2,容量is 6
    fmt.Printf("length of slice %d capacity %d",
    len(fruitslice), cap(fruitslice))
}
package main

import "fmt"

func testMake1() {
    var a []int
    a = make([]int, 5, 10)
    a[0] = 10
    //a[1] = 20
    fmt.Printf("a=%v addr:%p len:%d cap:%d
", a, a, len(a), cap(a))
    a = append(a, 11)
    fmt.Printf("a=%v addr:%p len:%d cap:%d
", a, a, len(a), cap(a))

    for i := 0; i < 8; i++ {
        a = append(a, i)
        fmt.Printf("a=%v addr:%p len:%d cap:%d
", a, a, len(a), cap(a))
    }
    //观察切片的扩容操作,扩容的策略是翻倍扩容
    a = append(a, 1000)
    fmt.Printf("扩容之后的地址:a=%v addr:%p len:%d cap:%d
", a, a, len(a), cap(a))
}
/*
a=[10 0 0 0 0] addr:0xc0000860a0 len:5 cap:10
a=[10 0 0 0 0 11] addr:0xc0000860a0 len:6 cap:10
a=[10 0 0 0 0 11 0] addr:0xc0000860a0 len:7 cap:10
a=[10 0 0 0 0 11 0 1] addr:0xc0000860a0 len:8 cap:10
a=[10 0 0 0 0 11 0 1 2] addr:0xc0000860a0 len:9 cap:10
a=[10 0 0 0 0 11 0 1 2 3] addr:0xc0000860a0 len:10 cap:10
a=[10 0 0 0 0 11 0 1 2 3 4] addr:0xc000098000 len:11 cap:20
a=[10 0 0 0 0 11 0 1 2 3 4 5] addr:0xc000098000 len:12 cap:20
a=[10 0 0 0 0 11 0 1 2 3 4 5 6] addr:0xc000098000 len:13 cap:20
a=[10 0 0 0 0 11 0 1 2 3 4 5 6 7] addr:0xc000098000 len:14 cap:20
扩容之后的地址:a=[10 0 0 0 0 11 0 1 2 3 4 5 6 7 1000] addr:0xc000098000 len:15 cap:20
*/

func testMake2() {
    var a []int
    a = make([]int, 5, 10)
    //a[5] = 100
    a = append(a, 10)
    fmt.Printf("a=%v
", a)

    b := make([]int, 0, 10)
    fmt.Printf("b=%v len:%d cap:%d
", b, len(b), cap(b))
    b = append(b, 100)
    fmt.Printf("b=%v len:%d cap:%d
", b, len(b), cap(b))
}

func main() {
    // testMake1()
    testMake2()
}

切片的再切片

package main

import "fmt"

func reslice() {
    a := [...]int{1, 2, 3, 4, 5, 6, 4, 7, 8}
    b := a[2:4]
    fmt.Printf("b = %d len(b) = %d cap(b)=%d
", b, len(b), cap(b))
    c := b[:cap(b)]
    fmt.Printf("c = %d len(c) = %d cap(c)=%d
", c, len(c), cap(c))
}

func main() {
    reslice()
}

/*
b = [3 4] len(b) = 2 cap(b)=7
c = [3 4 5 6 4 7 8] len(c) = 7 cap(c)=7
*/

 计算容量

package main

import "fmt"

func testCap() {
    a := [...]int{1, 2, 3, 4, 5, 6, 7}
    b := a[1:3]
    fmt.Print("b= %v  len(b) = %d, cap(b) = %d
", b, len(b), cap(b)) // 切片的容量 等于 原始素组的长度 减去 切片开始的索引
}

func main() {
    testCap()
}
package main
import ( 
    "fmt"
)
func main() { 
    fruitarray := […]string{
         "apple", "orange", "grape", "mango",
        "water melon", "pine apple", "chikoo"}
    fruitslice := fruitarray[1:3]
    //⻓度是2, 容量是6
    fmt.Printf("length of slice %d capacity %d
",
    len(fruitslice), cap(fruitslice))
    //再重新进⾏切⽚,不能⼤于数组fruitarray的⻓度,否则越界
    fruitslice = fruitslice[:cap(fruitslice)]
    fmt.Println("After re-slicing length is”,
    len(fruitslice), "and capacity is",cap(fruitslice))
}        

append操作

package main

import (
    "fmt"
)

func main() {
    cars := []string{"Ferrari", "Honda", "Ford"}
    //长度和容量都等于3
    fmt.Println("cars:", cars, "has old length", len(cars), "and capacity", cap(cars))
    cars = append(cars, "Toyota")
    //容量等于6
    fmt.Println("cars:", cars, "has new length",
        len(cars), "and capacity", cap(cars))
}
/*
cars: [Ferrari Honda Ford] has old length 3 and capacity 3
cars: [Ferrari Honda Ford Toyota] has new length 4 and capacity 6
*/

空切片

package main
import ( 
    "fmt"
)
func main() { 
    //定义names是一个空切片,长度和容量都等于0
    //不能对空切片进行访问,否则panic
    var names []string
     if names == nil {
          fmt.Println("slice is nil going to append")
          names = append(names, "John", "Sebastian", "Vinay")
          fmt.Println("names contents:",names)
    }
}    
package main

import "fmt"

func test() {
    var a []int

    fmt.Printf("addr = %p len=%d  cap =%d
", a, len(a), cap(a))
    // a[0]=100  报错

    if a == nil {
        fmt.Printf("a is nil
")
    }

    a = append(a, 100)
    fmt.Printf("addr = %p len=%d  cap =%d
", a, len(a), cap(a))
    a = append(a, 200)
    fmt.Printf("addr = %p len=%d  cap =%d
", a, len(a), cap(a))
    a = append(a, 300)
    fmt.Printf("addr = %p len=%d  cap =%d
", a, len(a), cap(a))
    a = append(a, 400)
    fmt.Printf("addr = %p len=%d  cap =%d
", a, len(a), cap(a))

}
/*
addr = 0x0 len=0  cap =0
a is nil
addr = 0xc0000100e0 len=1  cap =1
addr = 0xc000010100 len=2  cap =2
addr = 0xc00000a3c0 len=3  cap =4
addr = 0xc00000a3c0 len=4  cap =4
*/

func main() {
    test()
}

append一个切片

package main
import ( 
 "fmt"
)
func main() { 
 veggies := []string{"potatoes","tomatoes","brinjal"}
 fruits := []string{"oranges","apples"}
 //fruits后面的3个点表示展开fruits切片成一个个元素
 food := append(veggies, fruits...)
 fmt.Println("food:",food)
}
// food: [potatoes tomatoes brinjal oranges apples]
package main

import "fmt"

func test() {
    var a []int = []int{1, 2, 3}
    b := []int{4, 5, 6}
    c := append(a, b...)
    fmt.Printf("a=%v
", a)
    fmt.Printf("b=%v
", b)
    fmt.Printf("c=%v
", c)
}
/*
a=[1 2 3]
b=[4 5 6]
c=[1 2 3 4 5 6]
*/

func main() {
    test()
}

 切片传参

package main

import (
    "fmt"
)

//在函数内部修改numbers切⽚的值
func subtactOne(numbers []int) {
    for i := range numbers {
        numbers[i] -= 2
    }
}
func main() {
    nos := []int{8, 7, 6}
    fmt.Println("slice before function call", nos)
    subtactOne(nos)
    //nos修改生效了,说明切片是引用类型
    fmt.Println("slice after function call", nos)
}
/*
slice before function call [8 7 6]
slice after function call [6 5 4]
*/
package main

import "fmt"

func testSum(a []int) int {
    sum := 0
    for _, v := range a {
        sum += v
    }
    return sum
}

func testChange(a []int) {
    a[0] = 1000
}

func main() {
    a := [...]int{1, 2, 3, 4, 5, 6}
    // sum := testSum(a[:])
    // fmt.Printf("sum = %d", sum) // 21

    fmt.Printf("a=%v
", a)
    testChange(a[:])
    fmt.Printf("a=%v", a)

    /*
    a=[1 2 3 4 5 6]
    a=[1000 2 3 4 5 6]
    */
}

切片拷贝

package main

import (
    "fmt"
)

func main() {
    veggies := []string{"potatoes", "tomatoes", "brinjal"}
    fruits := []string{"oranges", "apples"}
    copy(veggies, fruits)
    fmt.Println(veggies, fruits) //[oranges apples brinjal] [oranges apples]
}
package main

import "fmt"

func testCopy() {
    a := []int{1, 2, 3}
    b := []int{4, 5, 6}

    copy(a, b)
    fmt.Printf("a = %v
", a) // [4,5,6]
    fmt.Printf("b = %v
", b) // [4,5,6]

    c := []int{1, 2}
    d := []int{4, 5, 6}

    e := copy(c, d)
    fmt.Printf("c = %v
", c) // [4,5]
    fmt.Printf("d = %v
", d) // [4,5,6]
    fmt.Printf("e = %v
", e) // 2

    b[0] = 100
    fmt.Printf("a = %v
", a) // [4,5,6]
    fmt.Printf("b = %v
", b) // [100 5 6]

    aa := [...]int{1, 2, 3, 4, 5, 6}
    bb := aa[:]
    cc := []int{10, 20, 30}
    copy(bb, cc)
    fmt.Printf("aa = %v
", aa) // [10 20 30 4 5 6]
    fmt.Printf("bb = %v
", bb) // [10 20 30 4 5 6]
    fmt.Printf("cc = %v
", cc) // [10 20 30]

}

func main() {
    testCopy()
}

切片遍历

var a [3]int
a[0] = 10
a[1] = 20
a[2] = 30
b := a[:]
for index, val := range b {
}
//和数组遍历一样

make和new区别

 make为内建类型slice、map和channel分配内存。

//初始化一个切片
s := make([]int, 10, 30)

 new用于各种类型的内存分配,new返回是一个指针。

 

原文地址:https://www.cnblogs.com/ctztake/p/10324561.html