• go语言3 数组, 切片, Maps, 切片当参数传递问题


    1 数组

    //数组:数组是同一类型元素的集合,在内存中连续存放
    package main
    import "fmt"
    
    func main() {
        //1 基本使用:定义
        //定义了一个大小为3的int类型数组
        //数组在定义阶段,大小和类型就固定了
        //var a [3]int    //只定义,没有初始化
        //fmt.Println(a)
    
        //2 使用数组(从0开始)
        //var a [3]int
        //a[2]=100
        //fmt.Println(a)
        //fmt.Println(a[0])
    
        //3 定义并赋初值
        //var a [3]int=[3]int{1,2,3}
        //var a =[3]int{1,2,3}
        //a := [3]int{1, 2, 3}
    
        //只给第2个位置设为99
        //a := [3]int{2:99}
        ////进阶版
        //a := [3]int{2:99,1:88}
        //fmt.Println(a)
    
        //4 数组的大小是类型的一部分
        //这两个不是一个类型
        //var a [2]int
        //var b [3]int
        //a=b
        //fmt.Println(a>b)
    
        //5 数组是值类型(当参数传递到函数中,修改不会改变原来的值)
        // go语言中,都是copy传递
        /*
        python中都是引用传递,一切皆对象,就是地址,当做参数传递是把地址传过去了
        python中比较特殊:可变类型和不可变类型
         */
    
        a :=[3]int{5,6,7}
        fmt.Println(a)
        test1(a)
        fmt.Println(a)
    
    func test1(a [3]int){    // 值类型传参为copy,内部修改不会改变原来的
        a[0] = 999
        fmt.Println(a)
    }
    
        //6 数组长度(len)
        //var a [3]int=[3]int{5,6,7}
        //fmt.Println(len(a))
    
        //7 循环数组
        //方式一
        //var a [3]int=[3]int{5,6,7}
        //for i:=0;i<len(a);i++{
        //    fmt.Println(a[i])
        //}
        //方式二
        //range:是一个关键字
        //var a [3]int=[3]int{5,6,7}
        //for i,v:=range a{
        //    fmt.Println(i)  //索引
        //    fmt.Println(v)  //数组的值
        //}
        //函数如果返回两个值,必须用两个值来接收
        //range是关键字,可以用一个值来接收,如果用一个值来接收,就是索引
        //for i:=range a{
        //    fmt.Println(i)  //索引
        //}
        //只取值,不取索引
        //for _,v:=range a{
        //    fmt.Println(v)  ////}
    
        //8 多维数组
        //定义一个二维数组
        //var a [3][2]int
        //定义并初始化
        var a [3][2]int=[3][2]int{{1,2},{4,5},{9,70}}
        //a[1][0]=999
        fmt.Println(a)
    
        //两种方式循环出二维数组
    }
    
    func test1(a [3]int)  {
        a[0]=999
        fmt.Println(a)
    }

    2 切片

    //切片是由数组建立的一种方便、灵活且功能强大的包装(Wrapper)。切片本身不拥有任何数据。它们只是对现有数组的引用。
    //切片底层依附于数组,无法删除元素
    package main
    import "fmt"
    
    func main() {
        //1 创建切片(基于一个数组创建)
        //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
        ////2 基于数组,切出一部分成为切片
        //// []int 中括号中没有东西,就是切片
        //var b []int
        //// 没有-1  没有步长
        //
        //b=a[0:3]  //前闭后开
        ////b=a[3:6]  //前闭后开
        ////b=a[:]  //前闭后开  从头切到尾
        ////b=a[3:]  //前闭后开
        //fmt.Println(b)
        //
        ////2 使用切片
        //fmt.Println(b[0])
    
        //3 切片的修改会影响底层数组,数组的修个也会影响切片
        //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
        //var b []int=a[0:3]  //前闭后开
        //
        //fmt.Println(a)    // [1 2 3 4 5 6 7 8 9]
        //fmt.Println(b)    // [1 2 3]
        //a[0]=999
        //b[2]=888
        //fmt.Println(a)    // [999 2 888 4 5 6 7 8 9]
        //fmt.Println(b)    // [999 2 888]
    
        // 4 切片的长度和容量
        //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
        //    //var b []int=a[2:3]  //前闭后开
    
        //fmt.Println(len(b))
        ////切片容量是9,意思是,可以往里追加值,追加成9个
        //fmt.Println(cap(b))
        //
        ////容量就是原数组的长度呗?对不对?不太对。。
        //b[0]=9999
        //fmt.Println(a)
        //fmt.Println(b)
    
        //5 追加值
        //var a [9]int=[9]int{1,2,3,4,5,6,7,8,9}
        //var b []int=a[2:3]  //前闭后开
        //b=append(b,1)
        //b=append(b,11,22,33,44,55)
        //fmt.Println(len(b))
        //fmt.Println(cap(b))  // 容量是7
        //fmt.Println(b)
        //fmt.Println(a)
        //到了数组的尾部,继续追加值
        //b=append(b,999)
        //fmt.Println(len(b))
        //fmt.Println(cap(b))  //容量是14
        ////总结1:当切片追加值,超过了切片容量,切片容量会翻倍,在原来容量基础上乘以2
        ////b=append(b,222,333,444,555,666,7,8)
        ////fmt.Println(len(b))
        ////fmt.Println(cap(b))  //容量是14
        //
        ////总结2:一旦超过了原数组, 就会重新申请数组,把数据copy到新数组,切片和原数组就没有关系了
        //fmt.Println(a)
        //fmt.Println(b)
        //a[8]=7777        // 不会影响b数组
        //fmt.Println(a)
        //fmt.Println(b)
    
        //6 通过make创建切片(底层也依附于数组)   只能定义,不能赋初值
        //var a []int
        //切片零值是什么? nil类型:是所有引用类型的空值
        //fmt.Println(a)
        //if a==nil{
        //    fmt.Println("我是空的")
        //}
    
        //3是长度,4是容量
        //var a []int=make([]int,3,4)
        //3是长度,3是容量
        //var a []int=make([]int,3)
        //fmt.Println(a)
        //if a==nil{
        //    fmt.Println("我是空的")
        //}
        //
        //fmt.Println(len(a))
        //fmt.Println(cap(a))
        //
        //a=append(a,55)
        //fmt.Println(a)
        //fmt.Println(len(a))
        //fmt.Println(cap(a))
    
        //6 切片定义并赋初值
        //var a []int=[]int{1,2,3}
        //fmt.Println(a)
        //fmt.Println(len(a))
        //fmt.Println(cap(a))
    
        //7 切片是引用类型,当参数传递,会修改掉原来的值
        //var a []int=[]int{1,2,3}
        //fmt.Println(a)
        //test3(a)
        //fmt.Println(a)
    
        //8 多维切片
        //var a [][]int=make([][]int,2,3)  // 创建出第一层切片实例化,第二层并未实例化
        //fmt.Println(a)
        //fmt.Println(a[0]==nil)
        ////会报错
        ////a[0][0]=999
        //// 如何做?(for循环完成初始化)
        //
        //a[0]=make([]int,2,3)
        //a[0][1]=999
        //fmt.Println(a)
        //a[1][0]=99999
    
        //定义并赋初值用的多
        //var a [][]int=[][]int{{1,2,3},{4,5,6,7,7,8}}
        ////跟上面不一样    切片为 个数为3的int类型数组
        //var a [][3]int=[][3]int{{1,2,3},{4,5,6}}
        //fmt.Println(a)
    
        //9 切片的copy
        //var a []int=make([]int,3,4)
        //var b []int=make([]int,2,6)
        //a[0]=11
        //a[1]=22
        //a[2]=33
        //b[0]=999
        //fmt.Println(a)
        //fmt.Println(b)
        //
        //copy(b,a)      // 目标   源   a中部分会覆盖b
        //fmt.Println(b)   // [11,22]  因为长度限制,取前两个
    
        //10 切片越界
        //var a []int=make([]int,3,4)
        //a[0]=11
        //a[1]=22
    
        //a[2]=33
        //
        //a=append(a,999)
        ////中括号取值,只能取到长度值,不能取到容联大小
        //fmt.Println(a[3])
    
        // 11 切片循环
        // 方式一
        var a []int=make([]int,3,4)
        //for i:=0;i<len(a);i++ {
        //    fmt.Println(a[i])
        //}
    
        // 方式二
        for i,v:=range a{
            fmt.Println(i)
            fmt.Println(v)
        }
    }
    
    func test3(a []int)  {
        a[0]=999
        fmt.Println(a)
    }

    3 Maps

    //maps:hash,字典,   key:value存储
    
    package main
    import "fmt"
    
    func main() {
        //1 map的定义和使用
        //map[key类型]value类型:key的类型必须可hash,key值:数字,字符串
        //map的零值:nil   它是一个引用类型
        //var a map[int]string
        //fmt.Println(a)
        //if a==nil{
        //    fmt.Println("我是空的")
        //}
    
        //2 定义了,没有初始化,使用
        //var a map[int]string
        //初始化用make
        //var a map[int]string=make(map[int]string)
        ////如果有,会修改,如果没有,会放入
        //a[1]="lqz"
        //a[1]="egon"
        //a[2]="99"
        //
        ////a["xx"] key值不能乱写
        //
        //fmt.Println(a)
    
        //3 获取元素
        //var a map[int]string=make(map[int]string)
        ////var a map[int]int=make(map[int]int)
        //fmt.Println(a[0])  //取出value值的空值  ""
        //fmt.Println(a)
    
        //统一的方案来判断value值是否存在
    
        //a[0] 可以返回两个值,一个是value值(可能为空),另一个是true或false(未赋值为false)
        //var a map[int]int=make(map[int]int)
        //a[0]=0
        //v,ok:=a[0]    // 因为已赋值,所以ok为true
        //fmt.Println(v)
        //fmt.Println(ok)
    
        //4 map 删除元素
        //var a map[int]int=make(map[int]int)
        //a[1]=11
        //a[2]=22
        //fmt.Println(a)
        ////根据key删(内置函数)
        //delete(a,1)
        //fmt.Println(a)
    
        //5 map 长度
        //var a map[int]int=make(map[int]int)
        //fmt.Println(len(a))
        //a[1]=11
        //a[2]=22
        //fmt.Println(len(a))
    
        //6 map 是引用类型
        //var a map[int]int=make(map[int]int)
        //a[1]=11
        //
        //test4(a)
        //fmt.Println(a)
    
        //7 Map 的相等性
        //var a map[string]string=make(map[string]string)
        //a["name"]="lqz"
        //var b map[string]string=make(map[string]string)
        //b["name"]="lqz"
        //
        ////不能这样判断,map只能跟nil比较
        //// if a==b{} // 因为map是引用类型,这样相当于比较两个地址,不支持直接这样比
        //if a==nil {
        //
        //}
    
        //8 循环map
        var a map[string]string=map[string]string{"name":"lqz","age":"19","sex":""}  // 赋初值
        //搞不了
        //for i:=0;i<len(a) ; i++ {
        //    fmt.Println(a[i])
        //
        //}
    
        //range循环   只能借助range
        for k,v:=range a{
            fmt.Println(k)
            fmt.Println(v)
        }
    
        // 9 map是无序的(python中字典从3.6以后有序了,3.6之前无序,底层如何实现的,看博客)
        // https://www.cnblogs.com/xiaoyuanqujing/articles/12008689.html
    }
    
    func test4(a map[int]int)  {
        a[1]=999
        fmt.Println(a)
    }

    切片当参数传递问题

    //切片传递问题
    package main
    import "fmt"
    
    func main() {
        //var a[]int=[]int{1,2,3}
        var a []int = make([]int, 2, 4)
        a[0] = 1
        a[1] = 2
        fmt.Println(a)
        fmt.Println(cap(a))
        test(a)
        fmt.Println(a) // [999 2]
    }
    func test(a []int) {
        a[0] = 999
        fmt.Println(a)
        a = append(a, 66)
        fmt.Println(a) // [999 2 66]
    }
    // 在go语言中素有参数传递都是copy传递
    
    /*
    切片{
        Length            int        切片长度
        Capacity        int        切片容量
        ZerothElement    *byte   指向底层数组的指针
    }
    copy了一份,append追加        两个切片引用的地址相同,但是是两个切片
    切片{
        Length            int        长度+1   // 至此,两个切边不同了
        Capacity        int        切片容量
        ZerothElement    *byte   指向底层数组的指针
    }
    */

    总结:

    // 1 前后端混合开发项目(DTL),在后端通过模板语言渲染成用户看到的html页面
    // 2 前后端分离(restful规范),xml格式,json
    
    //3 数组切片maps
    //4 数组:连续存储,同一种元素的集合
    -var a [4]int=[4]int{1,2,3,4}
    -a[4]  报错
    -数组是值类型(默认值:数组类型的0值)
    -循环数组 两种方式 range
    -多维数组:var a [3][4]string   取值,赋值 a[][]
    
    -这种定义方式 a:=[...]int{1,2,3}  // ...数组元素可以任意定义,但是定义完长度是固定的
    
    //5 切片:本身不存储数据,是对底层数组的引用(数组和切片变化会相互影响)
        -基于数组切出来 a[:]  
        -容量和长度 len  cap
        -切片追加 append(切片,切片存储类型的元素)
        -超出容量,重写申请一个两倍容量的数组,依附于这个数组(容量翻倍)
        -引用类型(空值:nil)
        -切片当做参数传递到函数中,在函数中调用append,会怎么样?
        -循环
        -多维切片
        -make创建切片
      -定义并初始化,创建切片  var a []int =[]int{1,2,3,4,5,5,6,7,8,8,9}
    
    //6 map:字典,hash
        -var a map[key类型]value的类型    
        -空值:nil类型,引用类型
        -初始化:
    -make(map[key类型]value的类型)  // var a map[int]string=make(map[int]string,10) 定义初始长度,提高性能
        -var a map[key类型]value的类型    =map[key类型]value的类型{key:value,key:value}
        -取值,赋值  
        -取值如果没有 v,ok:=a[key]
        -长度 len
        -循环 for k,v:=range map{}
        -map比较,只能跟nil比较
        -删除:内置函数delete
  • 相关阅读:
    球自由降落问题
    三次握手、四次挥手
    basicjava
    socket编程
    scanner和BufferedReader
    parseInt和valueOf
    正则表达式
    ASCII码常用值
    最大公约和最小公倍数
    查询语句
  • 原文地址:https://www.cnblogs.com/ludingchao/p/12757308.html
Copyright © 2020-2023  润新知