美文网首页让前端飞
【golang】3.0 指针、数组、range关键字、Slice

【golang】3.0 指针、数组、range关键字、Slice

作者: bobokaka | 来源:发表于2022-05-04 17:04 被阅读0次

    指针

    指针在go语言中是一个很重要的概念,但比c语言简单多了。

    指针简单在:指针不能运算
    参数传递:值传递还是引用传递。go语言只有值传递。

    值传递验证:

    package main
    
    import "fmt"
    
    func swap(a, b int) {
        a, b = b, a
    }
    
    func main() {
        a, b := 3, 4
        swap(a, b)
        fmt.Println(a, b)
    }
    
    
    image.png

    指针传递:

    package main
    
    import "fmt"
    
    func swap(a, b int) {
        a, b = b, a
    }
    func swapPrint(a, b *int) {
        *a, *b = *b, *a
    }
    
    func main() {
        a, b := 3, 4
        //swap(a, b)
        swapPrint(&a, &b)
        fmt.Println(a, b)
    }
    
    image.png

    数组

    数据的定义需要声明数组长度。

    package main
    
    import "fmt"
    
    func main() {
    
        var arr1 [5]int
        arr2 := [3]int{1, 3, 5}
        arr3 := [...]int{2, 4, 6, 8, 10}
    
        fmt.Println(arr1, arr2, arr3)
    }
    
    image.png

    二维数组

    package main
    
    import "fmt"
    
    func main() {
    
        var arr1 [5]int
        arr2 := [3]int{1, 3, 5}
        arr3 := [...]int{2, 4, 6, 8, 10}
    
        fmt.Println(arr1, arr2, arr3)
    
        //二维数组
        var grid [4][5]int
        var grid2 [4][5]bool
        fmt.Println(grid)
        fmt.Println(grid2)
    }
    
    
    image.png

    range关键字使用

    package main
    
    import "fmt"
    
    func main() {
    
        var arr1 [5]int
        arr2 := [3]int{1, 3, 5}
        arr3 := [...]int{2, 4, 6, 8, 10}
    
        fmt.Println(arr1, arr2, arr3)
    
        //二维数组
        var grid [4][5]int
        var grid2 [4][5]bool
        fmt.Println(grid)
        fmt.Println(grid2)
    
        //数组遍历
        //for i := 0; i < len(arr3); i++ {
        //如上可以写成如下,效果相等,i为下标,v为值
        for i, v := range arr3 {
            fmt.Println(arr3[i], v)
        }
        fmt.Println("*******************")
        // 如下验证值传递还是引用传递
        for i, v := range arr3 {
            v++
            fmt.Println(arr3[i], v)
        }
    
        // 如果只想用值
        for _, v := range arr3 {
            fmt.Println(v)
        }
    
    }
    
    image.png

    为什么要用range:


    image.png

    数组是值类型,可以更好的验证:

    package main
    
    import "fmt"
    
    func arrayDemo() {
    
        var arr1 [5]int
        arr2 := [3]int{1, 3, 5}
        arr3 := [...]int{2, 4, 6, 8, 10}
    
        fmt.Println(arr1, arr2, arr3)
    
        //二维数组
        var grid [4][5]int
        var grid2 [4][5]bool
        fmt.Println(grid)
        fmt.Println(grid2)
    
        //数组遍历
        //for i := 0; i < len(arr3); i++ {
        //如上可以写成如下,效果相等,i为下标,v为值
        for i, v := range arr3 {
            fmt.Println(arr3[i], v)
        }
        fmt.Println("*******************")
        // 如下验证值传递还是引用传递
        for i, v := range arr3 {
            v++
            fmt.Println(arr3[i], v)
        }
    
        // 如果只想用值
        for _, v := range arr3 {
            fmt.Println(v)
        }
    }
    
    func printArray(arr [5]int) {
        arr[0] = 100
        for i, v := range arr {
            fmt.Println(arr[i], v)
        }
    
    }
    
    func main() {
        arr3 := [...]int{2, 4, 6, 8, 10}
        printArray(arr3)
        fmt.Println("***********")
        fmt.Println(arr3)
    }
    
    image.png

    如果用指针,可以达到一个引用传递的效果。

    ......
    func printArrayPointer(arr *[5]int) {
        arr[0] = 100
        for i, v := range arr {
            fmt.Println(arr[i], v)
        }
    
    }
    
    func main() {
        arr3 := [...]int{2, 4, 6, 8, 10}
        //printArray(arr3)
        //fmt.Println("***********")
        //fmt.Println(arr3)
        printArrayPointer(&arr3)
        fmt.Println(arr3)
    }
    
    image.png

    这里可以看出,数组用起来很麻烦,需要指定数组的长度,更多的使用Slice(切片)

    Slice(切片)

    切片的使用:

    package main
    
    import "fmt"
    
    func main() {
        arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7}
        // 计算机的区间一般为半开半闭区间,及2,3,4,5
        s := arr[2:6]
        fmt.Println(arr, s)
    }
    
    image.png

    为了更好的理解切片,用例如下:

    package main
    
    import "fmt"
    
    func main() {
        arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
        // 计算机的区间一般为半开半闭区间,及2,3,4,5
        //s := arr[2:6]
        fmt.Println("arr[2:6] = ", arr[2:6])
        fmt.Println("arr[:6] = ", arr[:6])
        fmt.Println("arr[2:] = ", arr[2:])
        fmt.Println("arr[:] = ", arr[:])
    }
    
    image.png

    arr[2:6],相当于对arr的一个视图

    package main
    
    import "fmt"
    
    func updateSlice(s []int) {
        s[0] = 100
    }
    
    func main() {
        arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
        // 计算机的区间一般为半开半闭区间,及2,3,4,5
        //s := arr[2:6]
        //arr[2:6],相当于对arr的一个视图
        fmt.Println("arr[2:6] = ", arr[2:6])
        fmt.Println("arr[:6] = ", arr[:6])
        s1 := arr[2:]
        fmt.Println("arr[2:](s1) = ", s1)
        s2 := arr[:]
        fmt.Println("arr[:](s2) = ", s2)
    
        fmt.Println("After updateSlice(s1)")
        updateSlice(s1)
        fmt.Println(s1)
        fmt.Println(arr)
    
        fmt.Println("After updateSlice(s2)")
        updateSlice(s2)
        fmt.Println(s2)
        fmt.Println(arr)
    
    }
    
    image.png

    视图是告诉计算机,这是一个底层数据的视图,如果改掉将等同于整个数据的改动。

    也就是说,我们需要用指针达成的效果,可以如下进行:

    package main
    
    import "fmt"
    
    func arrayDemo() {
    
        var arr1 [5]int
        arr2 := [3]int{1, 3, 5}
        arr3 := [...]int{2, 4, 6, 8, 10}
    
        fmt.Println(arr1, arr2, arr3)
    
        //二维数组
        var grid [4][5]int
        var grid2 [4][5]bool
        fmt.Println(grid)
        fmt.Println(grid2)
    
        //数组遍历
        //for i := 0; i < len(arr3); i++ {
        //如上可以写成如下,效果相等,i为下标,v为值
        for i, v := range arr3 {
            fmt.Println(arr3[i], v)
        }
        fmt.Println("*******************")
        // 如下验证值传递还是引用传递
        for i, v := range arr3 {
            v++
            fmt.Println(arr3[i], v)
        }
    
        // 如果只想用值
        for _, v := range arr3 {
            fmt.Println(v)
        }
    }
    
    func printArray(arr [5]int) {
        arr[0] = 100
        for i, v := range arr {
            fmt.Println(arr[i], v)
        }
    
    }
    func printArrayPointer(arr *[5]int) {
        arr[0] = 100
        for i, v := range arr {
            fmt.Println(arr[i], v)
        }
    
    }
    
    func printArraySlice(arr []int) {
        arr[0] = 100
        for i, v := range arr {
            fmt.Println(arr[i], v)
        }
    }
    
    func main() {
        var arr1 [5]int
        arr3 := [...]int{2, 4, 6, 8, 10}
        //printArray(arr3)
        //fmt.Println("***********")
        //fmt.Println(arr3)
        //printArrayPointer(&arr3)
        //fmt.Println(arr3)
    
        printArraySlice(arr1[:])
        fmt.Println(arr1)
        printArraySlice(arr3[:])
        fmt.Println(arr3)
    }
    

    slice还可以继续切片。

    package main
    
    import "fmt"
    
    func updateSlice(s []int) {
        s[0] = 100
    }
    
    func main() {
        arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
        // 计算机的区间一般为半开半闭区间,及2,3,4,5
        //s := arr[2:6]
        //arr[2:6],相当于对arr的一个视图
        fmt.Println("arr[2:6] = ", arr[2:6])
        fmt.Println("arr[:6] = ", arr[:6])
        s1 := arr[2:]
        fmt.Println("arr[2:](s1) = ", s1)
        s2 := arr[:]
        fmt.Println("arr[:](s2) = ", s2)
    
        fmt.Println("After updateSlice(s1)")
        updateSlice(s1)
        fmt.Println(s1)
        fmt.Println(arr)
    
        fmt.Println("After updateSlice(s2)")
        updateSlice(s2)
        fmt.Println(s2)
        fmt.Println(arr)
    
        // slice还可以进一步slice
        fmt.Println("Re slice")
        fmt.Println(s2)
        s2 = s2[:5]
        fmt.Println(s2)
        s2 = s2[2:]
        fmt.Println(s2)
    }
    
    image.png

    切片的复杂用法

    package main
    
    import "fmt"
    
    func updateSlice(s []int) {
        s[0] = 100
    }
    
    func sliceDemo(arr []int) {
        // 计算机的区间一般为半开半闭区间,及2,3,4,5
        //s := arr[2:6]
        //arr[2:6],相当于对arr的一个视图
        fmt.Println("arr[2:6] = ", arr[2:6])
        fmt.Println("arr[:6] = ", arr[:6])
        s1 := arr[2:]
        fmt.Println("arr[2:](s1) = ", s1)
        s2 := arr[:]
        fmt.Println("arr[:](s2) = ", s2)
    
        fmt.Println("After updateSlice(s1)")
        updateSlice(s1)
        fmt.Println(s1)
        fmt.Println(arr)
    
        fmt.Println("After updateSlice(s2)")
        updateSlice(s2)
        fmt.Println(s2)
        fmt.Println(arr)
    
        // slice还可以进一步slice
        fmt.Println("Re slice")
        fmt.Println(s2)
        s2 = s2[:5]
        fmt.Println(s2)
        s2 = s2[2:]
        fmt.Println(s2)
    
    }
    
    func main() {
        arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
        //sliceDemo(arr[:])
    
        s1 := arr[2:6]
        fmt.Println(s1)
        s2 := s1[3:5]
        fmt.Println(s2)
    }
    

    如上代码,是不报错的:


    image.png

    涉及到视图的原理:


    image.png
    image.png
    image.png

    所以可以如下打印:

    ......
    func main() {
        arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
        //sliceDemo(arr[:])
        fmt.Println("arr=", arr)
        s1 := arr[2:6]
        s2 := s1[3:5]
        fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
        fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n", s2, len(s2), cap(s2))
    }
    
    image.png

    切片扩展元素

    package main
    
    import "fmt"
    
    func updateSlice(s []int) {
        s[0] = 100
    }
    
    func sliceDemo(arr []int) {
        // 计算机的区间一般为半开半闭区间,及2,3,4,5
        //s := arr[2:6]
        //arr[2:6],相当于对arr的一个视图
        fmt.Println("arr[2:6] = ", arr[2:6])
        fmt.Println("arr[:6] = ", arr[:6])
        s1 := arr[2:]
        fmt.Println("arr[2:](s1) = ", s1)
        s2 := arr[:]
        fmt.Println("arr[:](s2) = ", s2)
    
        fmt.Println("After updateSlice(s1)")
        updateSlice(s1)
        fmt.Println(s1)
        fmt.Println(arr)
    
        fmt.Println("After updateSlice(s2)")
        updateSlice(s2)
        fmt.Println(s2)
        fmt.Println(arr)
    
        // slice还可以进一步slice
        fmt.Println("Re slice")
        fmt.Println(s2)
        s2 = s2[:5]
        fmt.Println(s2)
        s2 = s2[2:]
        fmt.Println(s2)
    
    }
    
    func main() {
        arr := [...]int{4, 0, 1, 2, 3, 4, 5, 6, 7}
        //sliceDemo(arr[:])
        fmt.Println("arr=", arr)
        s1 := arr[2:6]
        s2 := s1[3:5]
        fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n", s1, len(s1), cap(s1))
        fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n", s2, len(s2), cap(s2))
    
        s3 := append(s2, 10)
        fmt.Println("s3=", s3)
        s4 := append(s3, 11)
        fmt.Println("s4=", s4)
        s5 := append(s4, 12)
        fmt.Println("s3,s4,s5=", s3, s4, s5)
        fmt.Println("arr=", arr)
    }
    
    image.png

    这里发现arr的11和12不见了。


    image.png

    更深入测试

    package main
    
    import "fmt"
    
    func printSlice(s []int) {
        fmt.Printf("len=%d,cap=%d\n", len(s), cap(s))
    }
    
    func main() {
        var s []int
    
        for i := 0; i < 100; i++ {
            printSlice(s)
            s = append(s, 2*i+1)
        }
        fmt.Println(s)
    }
    
    

    运行结果如下:

    len=0,cap=0
    len=1,cap=1
    len=2,cap=2
    len=3,cap=4
    len=4,cap=4
    len=5,cap=8
    len=6,cap=8
    len=7,cap=8
    len=8,cap=8
    len=9,cap=16
    len=10,cap=16
    len=11,cap=16
    len=12,cap=16
    len=13,cap=16
    len=14,cap=16
    len=15,cap=16
    len=16,cap=16
    len=17,cap=32
    len=18,cap=32
    len=19,cap=32
    len=20,cap=32
    len=21,cap=32
    len=22,cap=32
    len=23,cap=32
    len=24,cap=32
    len=25,cap=32
    len=26,cap=32
    len=27,cap=32
    len=28,cap=32
    len=29,cap=32
    len=30,cap=32
    len=31,cap=32
    len=32,cap=32
    len=33,cap=64
    len=34,cap=64
    len=35,cap=64
    len=36,cap=64
    len=37,cap=64
    len=38,cap=64
    len=39,cap=64
    len=40,cap=64
    len=41,cap=64
    len=42,cap=64
    len=43,cap=64
    len=44,cap=64
    len=45,cap=64
    len=46,cap=64
    len=47,cap=64
    len=48,cap=64
    len=49,cap=64
    len=50,cap=64
    len=51,cap=64
    len=52,cap=64
    len=53,cap=64
    len=54,cap=64
    len=55,cap=64
    len=56,cap=64
    len=57,cap=64
    len=58,cap=64
    len=59,cap=64
    len=60,cap=64
    len=61,cap=64
    len=62,cap=64
    len=63,cap=64
    len=64,cap=64
    len=65,cap=128
    len=66,cap=128
    len=67,cap=128
    len=68,cap=128
    len=69,cap=128
    len=70,cap=128
    len=71,cap=128
    len=72,cap=128
    len=73,cap=128
    len=74,cap=128
    len=75,cap=128
    len=76,cap=128
    len=77,cap=128
    len=78,cap=128
    len=79,cap=128
    len=80,cap=128
    len=81,cap=128
    len=82,cap=128
    len=83,cap=128
    len=84,cap=128
    len=85,cap=128
    len=86,cap=128
    len=87,cap=128
    len=88,cap=128
    len=89,cap=128
    len=90,cap=128
    len=91,cap=128
    len=92,cap=128
    len=93,cap=128
    len=94,cap=128
    len=95,cap=128
    len=96,cap=128
    len=97,cap=128
    len=98,cap=128
    len=99,cap=128
    [1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 
                                                                                    57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 101 103 105 10
                                                                                   07 109 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143 145 14
                                                                                   47 149 151 153 155 157 159 161 163 165 167 169 171 173 175 177 179 181 183 185 18
                                                                                   87 189 191 193 195 197 199]
    
    Process finished with the exit code 0
    
    

    如果声明一个切片,但不初始化数据。

    package main
    
    import "fmt"
    
    func printSlice(s []int) {
        fmt.Printf("%v,len=%d,cap=%d\n", s, len(s), cap(s))
    }
    
    func main() {
        //var s []int
    
        //for i := 0; i < 100; i++ {
        //  printSlice(s)
        //  s = append(s, 2*i+1)
        //}
        //fmt.Println(s)
    
        // 如果需要指定一个可变数组,但不知道值,go叫切片,可以如下声明
        s2 := make([]int, 16)
        // 要求初始化10个数据要存储,但数组长度为32
        s3 := make([]int, 10, 32)
        printSlice(s2)
        printSlice(s3)
    }
    
    image.png

    Slice(切片)拷贝

    package main
    
    import "fmt"
    
    func printSlice(s []int) {
        fmt.Printf("%v,len=%d,cap=%d\n", s, len(s), cap(s))
    }
    
    func main() {
        //var s []int
    
        //for i := 0; i < 100; i++ {
        //  printSlice(s)
        //  s = append(s, 2*i+1)
        //}
        //fmt.Println(s)
        fmt.Println("Created Slice")
        s1 := []int{2, 4, 6, 8}
        // 如果需要指定一个可变数组,但不知道值,go叫切片,可以如下声明
        s2 := make([]int, 16)
        // 要求初始化10个数据要存储,但数组长度为32
        s3 := make([]int, 10, 32)
        printSlice(s2)
        printSlice(s3)
    
        fmt.Println("Copying slice")
        copy(s2, s1)
        printSlice(s2)
    
        fmt.Println()
    }
    
    image.png

    常用的:删除头和尾

    package main
    
    import "fmt"
    
    func printSlice(s []int) {
        fmt.Printf("%v,len=%d,cap=%d\n", s, len(s), cap(s))
    }
    
    func main() {
        //var s []int
    
        //for i := 0; i < 100; i++ {
        //  printSlice(s)
        //  s = append(s, 2*i+1)
        //}
        //fmt.Println(s)
        fmt.Println("Created Slice")
        s1 := []int{2, 4, 6, 8}
        // 如果需要指定一个可变数组,但不知道值,go叫切片,可以如下声明
        s2 := make([]int, 16)
        // 要求初始化10个数据要存储,但数组长度为32
        s3 := make([]int, 10, 32)
        printSlice(s2)
        printSlice(s3)
    
        fmt.Println("Copying slice")
        copy(s2, s1)
        printSlice(s2)
    
        //删除任意位置
        fmt.Println("Deleting elements from slice")
        s2 = append(s2[:3], s2[4:]...)
        printSlice(s2)
    
        //删除头
        fmt.Println("Popping from front")
        front := s2[0]
        s2 = s2[1:]
        fmt.Println(front)
        printSlice(s2)
        //删除尾
        fmt.Println("Popping from back")
        tail := s2[len(s2)-1]
        s2 = s2[:len(s2)-1]
        fmt.Println(tail)
        printSlice(s2)
    
    }
    
    image.png

    相关文章

      网友评论

        本文标题:【golang】3.0 指针、数组、range关键字、Slice

        本文链接:https://www.haomeiwen.com/subject/ktwwyrtx.html