Go语言数组和切片
2018-09-23 本文已影响0人
超级皮波9
数组
- 数组概念 数组就是用于保存一组相同类型的数据
- 定义格式
var arr [3]int //定义一个int类型的数组
- 操作数组的格式
arr [ 索引 / 下标]
//例如
arr[0] , arr[1] , arr [2]
- 数组的初始化 (赋值)
- 先定义再初始化
-
注意点
GO语言可以先定义再一次性全部初始化
var arr [3]int //先定义
arr = [3]int{1,2,3} // 全部初始化
var arr [3]int // 逐个初始化
arr[0] = 111
arr[1] = 222
arr[2] = 333
- 定义同时初始化
var arr[3]int = [3]int{1,2,3} / 完全初始化
arr := [3]int{1,2,3} / 第二中格式 企业开发经常使用
fmt.Println(arr[0]) //1
fmt.Println(arr[1]) //2
fmt.Println(arr[2]) //3
var arr[3]int = [3]int{1,2} / 部分初始化
- 指定元素初始化
package main
import "fmt"
func main() {
var arr [3]int = [3]int{2:9} // 相当于指定arr[2] = 9
fmt.Println(arr[0]) //0
fmt.Println(arr[1]) //0
fmt.Println(arr[2]) //9
}
- 省略数组个数的方式
[...]
package main
import "fmt"
func main() {
arr := [...]int{1,2,3,4,5,6,7,8,9} / [...] 系统会自动识别添加了多少个元素
fmt.Println(arr[0]) //1
fmt.Println(arr[1]) //2
fmt.Println(arr[2]) //3
fmt.Println(arr[3]) //4
fmt.Println(arr[4]) //5
fmt.Println(arr[5]) //6
fmt.Println(arr[6]) //7
fmt.Println(arr[7]) //8
fmt.Println(arr[8]) //9
}
数组的注意点
- 数组在GO语言中是值类型,所以数组之间的赋值是拷贝关系 而不是指向关系
package main
import "fmt"
func main() {
arr := [3]int{1,2,3}// 定义一个数组arr
var num[3]int // 定义一个数组num
num = arr // 让数组arr 赋值给数组 num
num[1] = 666 // 让数组 num[1] = 666
fmt.Println("arr = ",arr) //arr = [1 2 3]
fmt.Println("num = ",num) //num = [1 666 3]
}
package main
import "fmt"
func main() {
ages := [3]int{1,2,3}
change(ages)
fmt.Println("ages = ",ages) // ages = [1 2 3]
}
func change(arr [3]int){
arr[1] = 666
}
- 如果想让两个数组之间赋值 那么两个数组,数据类型,元素个数 都要相同才可以
package main
import "fmt"
func main() {
var arr [3]int= [3]int{1,2,3} // 数据类型 [3] int
var num [3]int // 数据类型 [3] int
num = arr
fmt.Println("arr = ",arr) // arr = [1,2,3]
fmt.Println("num = ",num) // num = [1,2,3]
}
- 如果数组中的元素支持 == , !=操作,而且两个数组数据类型一样的话,那么数组也支持 == , != 操作
package main
import "fmt"
func main() {
var arr[3]int = [3]int{1,2,3}
var arr1[3]int = [3]int{1,2,4}
res := arr == arr1 // 判断两个数组是否相等返回 false
fmt.Println(res) // false
}
数组的遍历
package main
import "fmt"
func main() {
arr := [5]int{10,20,30,40,50}
for i:=0;i<5;i++{
fmt.Println("arr[",i,"] = ",arr[i])
}
/*
arr[ 0 ] = 10
arr[ 1 ] = 20
arr[ 2 ] = 30
arr[ 3 ] = 40
arr[ 4 ] = 50
*/
}
- Go语言中的高级for循环也可以用来遍历数组
package main
import "fmt"
func main() {
arr := [5]int{1,2,3,4,5}
for index,value := range arr{ // index ==数组下标/索引 value== 数组元素的值
fmt.Println(index,value)
}
}
二维数组
- 定义格式
var 数组名称 [ 行数 ] [ 列数 ] 数据类型
var 数组名称 [一维数组的个数] [ 每个一维数组元素的个数 ] 数据类型
var arr [2][3]int
- 实例
package main
import "fmt"
func main() {
// 定义二维数组第1种
var arr[2][3]int = [2][3]int{
{1,2,3},
{4,5,6}, // 逗号不能省略
}
fmt.Println(arr)
// 定义二维数组第2种
arr1 := [2][3]int{
{7,8,9},
{10,11,12},
}
fmt.Println(arr1)
// 定义二维数组第3种
arr2 := [...][3]int{ //[...] 省略后系统会自己识别
{111,222,333},
{444,555,666},
}
fmt.Println(arr2)
}
- 二维数组的使用
arr[ 0 ][ 0 ] -->下标获取 ---代表第一个一维数组的第一个元素
- 二维数组遍历
package main
import "fmt"
func main() {
arr := [2][3]int{
{1,2,3},
{4,5,6},
}
for i:=0;i<2;i++{
for j:=0;j<3;j++{
fmt.Println(arr[i][j])
}
}
}
切片
- Go语言中的数组一旦确定长度就不能改变了,为了解决这个问题而诞生了一种新的数据类型 切片
-
概念
切片简单理解的话就是一个可变长度的数组
var sce[]int = []int{ } --- 这里arr不是数组了 是切片
切片的底层实现原理是一个结构体,结构体里有一个指针指向数组
所有的数据都是保存在指向的那个数组中
type slice struct {
array unsafe.Pointer // 指向底层数组的指针
len int //切片的长度(保存了多少个元素)
cap int // 切片容量(能保存多少个元素)
}
如何创建切片
1. 通过数组来创建
格式 [起始位置 : 结束位置 ] ---- 从起始位置开始截取,直到结束位置, 但是不包括结束位置
-
注意
截取了多少个元素,len
就等于几
容量(cap)
就等于 数组长度 减去 起始位置 - 实例
package main
import "fmt"
func main() {
//下标 0 1 2 3 4
var arr[5]int = [5]int{1,2,3,4,5}
var sclie []int = arr[2:4] // 代表从数组下标为2的位置开始截取到下标4 但是不包括下标4里的5
fmt.Println(sclie) // [ 3 , 4 ]
}
- 注意点 如果只写起始位置的 会截取到数组最后
package main
import "fmt"
func main() {
//下标 0 1 2 3 4
var arr[5]int = [5]int{1,2,3,4,5}
var sclie []int = arr[2:] // 只写开始位置
fmt.Println(sclie) // [3,4,5]
}
- 注意点 如果只写结束位置的话 会从数组最开始截取
package main
import "fmt"
func main() {
//下标 0 1 2 3 4
var arr[5]int = [5]int{1,2,3,4,5}
var sclie []int = arr[:3] // 只写结束位置
fmt.Println(sclie) // [1,2,3]
}
- 注意点 如果什么都不写会将整个数组截取下来
package main
import "fmt"
func main() {
//下标 0 1 2 3 4
var arr[5]int = [5]int{1,2,3,4,5}
var sclie []int = arr[:]
fmt.Println(sclie) // [1,2,3,4,5]
}
1.1 通过数组来创建
格式 数组[ 起始位置 : 结束位置 : max ]
- 不指定第三个参数 MAX 情况下
package main
import "fmt"
func main() {
var arr[5]int = [5]int{1,2,3,4,5}
var sce []int = arr[0:2]
fmt.Println(len(sce)) // len == 结束位置 - 起始位置
fmt.Println(cap(sce)) // cap容量 == 数组长度 - 起始位置
}
- 指定第三个参数 MAX 下
1.如果指定了第三个参数max , 那么切片的容量就等于 max减去 起始位置
2.MAX 必须大于等于结束位置
package main
import "fmt"
func main() {
var arr[5]int = [5]int{1,2,3,4,5}
var sce []int = arr[1:2:4] // 1 起始位置 2 结束位置 4 MAx
fmt.Println(len(sce)) // len = 1
fmt.Println(cap(sce)) // cap = max - 1(起始位置) = 4-1 = 3
}
2. 通过函数make来创建切片
var sce [ ] 参数1 = make ( [ ] 参数1 , 参数2 int , 参数3 int )
第一个参数代表创建什么数据类型的切片------> [] + 数据类型
第二个参数代表创建的切片保存了几个元素-----> 参数2 == len
第三个参数代表创建的切片容量是多少 ----> 参数3 == cap
- 实例
package main
import "fmt"
func main() {
var sce []int = make([]int,2,3) // 格式1
sce := make([]int,2,3) // // 格式2
fmt.Println(sce) // [0 , 0]
}
-
注意点
第三个参数可以省略,如果省略 切片的容量就等于第二个参数
sce := make([]int,2) // 那么切片的容量就等于第二个参数的值
3. 通过Go语言的语法来创建切片
package main
func main() {
var sce [ ]int = []int{1,2,3} // [ ]中没有数字和 [...] 都是切片不是数组
sce := [ ]int{1,2,3} // [ ]中没有数字和 [...] 都是切片不是数组
}
- 可以通过len ( ) 函数和 cap ( ) 函数计算出切片的长度和容量
fmt.Println( len( sce ) )
fmt.Println( cap( sce ) )
切片的使用
修改切片的值
package main
import "fmt"
func main() {
sce := []int{1,6}
sce[1] = 666
fmt.Println("sce = "sce) //sce = [1 ,666]
}
给切片增加数据
- 可以通过预先定义好的函数给切片增加数据 , 但是索引长度不能超过切片的len
-
append()函数会重新分配一个切片
作用 就是在切面len后追加数据
append( 切片, 数据) ---- 会重新返回一个切片
package main
import "fmt"
func main() {
var sce []int = make([]int,2,5)
fmt.Println(sce) // sce =[0 0]
sce[0] = 1
sce[1] = 2
sce[2] = 3 ---->会报错 超出了切片的len 2
fmt.Println(sce)
sce = append(sce,3)
fmt.Println(sce) // sce = [1 2 3]
}
- 注意点
- 如果超过切片的
容量
,且切片容量在1024内
,那么切片的容量就会变成原先的2倍
package main
import "fmt"
func main() {
var sce []int = make([]int,2)
fmt.Println(sce) // sce =[0 0]
sce[0] = 1
sce[1] = 2
sce = append(sce,3)
fmt.Println(len(sce)) // 储存了3个元素
fmt.Println(cap(sce)) // 容量翻倍 为4
fmt.Println(sce) // sce = [1 2 3]
}
- 如果超过切片的
容量
,且切片容量超过1024
,那么切片的容量会增加原先的切片容量的1/4
package main
import "fmt"
func main() {
var sce []int = make([]int,1024,1024)
sce = append(sce,1025)
fmt.Println(len(sce)) // 储存了3个元素 len = 1025
fmt.Println(cap(sce)) // 容量增加1/4 cap =1280
}
删除切片中的数据
package main
import "fmt"
func main() {
//下标 0 1 2 3 4
sce := []int{1,3,5,7,9}
index := 2 // 想要删除元素的下标
sce = append(sce[:index] , sce[index+1:]...)
fmt.Println("sce = ",sce) //sce = [1 3 7 9]
}
复制切片中的数据
- copy( ) 函数格式
copy(参数1,参数2)
参数1--->目标切片 指将要被赋值的切片
参数2--->原切片 指要复制的切片
系统会将原切片复制 然后赋值给目标切片 ----系统会以目标切片为主来赋值
- 实例
package main
import "fmt"
func main() {
//下标 0 1 2 3 4
sce := []int{1,3,5,7,9} //原切片
sce1 := []int{0,0,0} // 目标切片
copy(sce1,sce)
fmt.Println("sce1 = ",sce1) // sce1 = [1,3,5]
}
切片注意点
- 切片可以生成新的切片,两个切片底层指向同一个数组
- 切片如果没有初始化是不能使用的
- 切片不支持 == != 操作
- go语言中字符串的底层就是切片,因此可以通过字符串来生成切片
package main
import "fmt"
func main() {
var str string = "www.jianshu.com"
sce := make([]byte,len(str))
copy(sce,str)
fmt.Printf("sce = %s\n ",sce) // sce = www.jianshu.com
}
切片和数组区别
- [] 中没有数子的就是切片 , [] 中有数字和[...]的是数组
- 数组
package main
func main() {
var arr1 [2]int = [2]int{1,6}
var arr2 = [2]int{1,6}
arr3 := [2]int{1,6}
arr4 := [...]int{1,2,3,4,5,6}
}
- 切片
package main
func main() {
var sce1 []int = []int{1,6}
var sce2 = []int{1,6}
sce3 := []int{1,6}
}
-
数组
作为函数的参数
,是值传递,在函数内修改形参,不会影响函数外的实参
package main
import "fmt"
func main() {
arr := [3]int{1,2,3}
fmt.Println("arr = ",arr) // arr = [1 2 3]
change(arr)
fmt.Println("arr = ",arr) // arr = [1 2 3]
}
func change (num [3]int){
num[0] = 666
}
-
切片作为
函数
的参数
,是地址传递(指针)
在函数内修改形参,会影响到函数外的实参
package main
import "fmt"
func main() {
sce := []int{1,2,3}
fmt.Println("sce = ",sce) // sce = [1 2 3]
change(sce)
fmt.Println("sce = ",sce) // sce = [1 666 3]
}
func change (num []int){
num[1] = 666
}