GoLang:数组、切片

学习自:GoLang学习手册89页

2)操作数组的几种方式

①数组名:arr[i]

②指针:(*p)[i]

③指针:p[i]

1
2
3
4
5
6
7
8
9
10
11
//①数组名:arr[i]
//②指针:(*p)[i]
//③指针:p[i]
 
var p *[3]int
var arr [3]int=[3]int{1,2,3}
p=&arr
<br>//三种方法
arr[2]
(*p)[2]
p[2]

1、一维数组

1)定义:var 名称 [数量] 类型

  • 定义但不初始化:var 名称 [数量] 类型

    //只定义不初始化
    var arr [3]int //定义时未指定初值,会采用该类型的默认值[0,0,0]
  • 定义时初始化:var 名称 [数量] 类型=[数量]类型{值1,值2,...}

    复制代码
    //完全初始化
    var arr [3]int = [3]int{1,3,5}
    //部分初始化
    var arr [3]int = [3]int{1,3} //[1,3,0]
    //部分初始化,指定具体位置上的元素进行初始化 var arr [3]int = [3]int{0:8,2:9}//0号索引赋值8,2号索引赋值9,1号取默认0
    //省略类型与长度,...会根据元素个数自动确认数组长度 arr := [...]int{1,3,5}
    //省略类型与长度,但需指定最后一个元素的值 arr := [...]int{6:5}//索引为6的元素,赋值5
    复制代码
  • 定义后初始化:

    复制代码
    var arr [3]int
    
    //依次初始化
    arr[0]=1
    arr[1]=2
    arr[2]=3
    
    //一次初始化
    arr=[3]int{1,2,3}
    复制代码

2)访问

数组长度:len(arr)

打印整个数组:fmt.Println(arr)

索引访问:arr[i] i从0开始

遍历

复制代码
arr := [...]int{1,3,5}

//正常for循环
for i:=0;i<len(arr);i++{
    fmt.Println(i,arr[v])
}

//for...range
for i,v := range arr{
    fmt.Println(i,v)
}
复制代码

3)比较

数组的类型要同时考虑①内部元素类型;②数组长度。因此[3]int和[4]int就不是同一种类型。

数组可以用==和!=进行相等判断

  • 进行相等判断的数组必须具有同类型——相同的元素类型+长度;
  • 不同类型的数组,无法比较——不是指不相等,而是连==比较的操作都无法进行(会报错);
  • 只有当内含元素支持==、!=,数组才会支持;
  • 比较时,会依次比较内部元素

2、二维数组

arr := [...][列数]类型 { {行1},{行2},... }

arr := [...][3]int{
    {1,2,3},
    {4,5,6},
}

fmt.Println(arr) //[[1,2,3] [4,5,6]]

3、切片

理解:动态数组

本质:结构体

//源码
type slice struct{
    array unsafe.Pointer //指向底层数组指针
    len int //切片长度——已经存了多少了长度
    cap int//切片容量——总共可以保存多少
可以通过len(sce)、cap(sce)获取切片长度(当前)容量(最大)

1)创建

①通过数组创建:sce:=arr[start:end]

说明:

  • 提取arr从start开始,共(end-start)个元素;

  • 提取arr索引从start到end-1的元素

  arr:=[...]int{1,2,3,4,5}
  sce:=arr[0:2] //[1,2]
  fmt.Println(sce,len(sce),cap(sce))//[1,2] 2 5

补充:

  • start、end可以只写其中一个(不写start默认从开头切,不写end默认切到最后),也可以都不写(默认从开头到结尾)

sce与arr的关系

  • sce的地址arr[start]的地址相同
  • len=end-start
  • cap=len(arr)-start(少了start之前索引处的元素)

②make创建:make(类型,长度,容量)

说明:内部先创建一个相同的数组,再让切片指向它。如果没容量,默认和长度一样。
sce:=make([]int,3,5)
fmt.Println(sce,len(sce),cap(sce))//[0,0,0] 3 5

//内部实现原理
arr:=[5]int{0,0,0}
sce=arr[0,3]

③Go语法糖:sce := [ ]int{值1,值2,值3}

说明:和创建数组相同,但是不指定长度,此法创建的切片,len==cap

sce:=[]int{1,3,5}
fmt.Println(sce,len(sce),cap(sce))//[1,3,5] 3 3

2)使用

①访问

访问:sce[索引]

注意:

  • 索引不能超过len
  • 可以修改sce指定索引处的值

②追加、扩容:append

如果希望追加时自动扩容,需要用append方法:

  • append在切片末尾(sec[len]处)添加一个元素,返回操作后的sce;
  • 如果追加后未超过cap,返回原切片;如果超过了,则返回扩容后的新切片
  • 扩容——每次扩容都使cap×2

③拷贝:copy(目标切片,源切片)

作用:将源切片中的数据拷贝到目标切片中

说明:

  • 拷贝后的切片地址和拷贝前的切片相同,二者底层指向相同数组(意味着二者在物理地址上相同,对其中任何一个的修改都会影响另一个)
  • 对拷贝后切片的修改,会导致拷贝前切片的变化;
  • 拷贝时以小容量为准:如果目标切片的cap比原切片大,那会把原切片全部拷贝过去,如果比原切片小,则只拷贝目标切片容量大小的数据

注意:

  • 可以对切片进行切片操作得到新的切片,两个切片底层指向同一个数组,对新切片的修改会影响原切片的值(甚至append之后,会使原切片中指定位置处的值被修正为该新加值):
    arr:=[...][1,3,5,7,9]
    sce1:=arr[0:4]
    sce2:=sce1[0:3]
  • 两个切片不支持==、!=运算,切片只支持和nil进行相等判断:
    fmt.Println(sce1==sce2)//编译报错
    fmt.Println(sce1!=nil)
    fmt.Println(sce2==nil)
  • 只是声明一个切片,而没有实际用make创建是不能使用的
    var sce []int
    sce[0]=2//编译报错
  • 字符串底层是[byte]数组,因此字符串也支持切片:
    str:="abcdefg"
    sce1:=str[3:]
    sce2:=make([]byte,10)
    copy(sce2,str)
    fmt.Println(sce2)//[97 98 99 100...]

     

 

posted @   ShineLe  阅读(110)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
点击右上角即可分享
微信分享提示