go 学习笔记之数组和切片 map 指针

数组

  • 数组是同一种数据元素的集合。在go语言中,数据从声明时就确定成员类型,使用时可以修改数据成员,但是数组大小不可变化

数组的声明

  • 数组是存放元素的容器
  • 必须指定存放的元素的类型和容量(长度)
  • 数组的长度是数组类型的一部分
var a1 [3]bool // 数组长度为3的bool数组
var a2 [4]bool // 数组长度为4的bool数组
//a1和a2不是同一种类型一种是[3]bool 一种是[4]bool
fmt.Printf("a1:%T a2:%T\n", a1, a2)
// 结果 a1:[3]bool a2:[4]bool

数组的初始化

  • 如果不初始化:默认元素都是零值(布尔值:false, 整型和浮点型都是0, 字符串:"")

    fmt.Println(a1, a2)
    //结果:[flase,flase,flase] [flase,flase,flase,flase]
    
  • 初始化方式1

    a1 = [3]bool{true, true, true}
    fmt.Println(a1)
    //结果:[true,true,true]
    
  • 初始化方式2 根据初始值自动推断数组长度多少

    格式 数组长度写…

a10 := [...]int{0, 1, 2, 3, 4, 4, 5, 6, 7}
fmt.Println(a10)
// 结果 [0 1 2 3 4 4 5 6 7]
  • 初始化方式3:根据索引来初始化

    a3 := [5]int{0: 1, 4: 2}
    fmt.Println(a3)
    // 结果 [1 0 0 0 2]
    

数组的遍历

// 数组的遍历
citys := [...]string{"北京", "上海", "深圳"} // 索引:0~2 citys[0],citys[1],citys[2]
// 1. 根据索引遍历
for i := 0; i < len(citys); i++ {
	fmt.Println(citys[i])
}
// 2. for range遍历
for i, v := range citys {
	fmt.Println(i, v)
}

二维数组

// 多维数组
// [[1 2] [3 4] [5 6]]
var a11 [3][2]int
a11 = [3][2]int{
	[2]int{1, 2},
	[2]int{3, 4},
	[2]int{5, 6},
}
fmt.Println(a11)

// 多维数组的遍历
for _, v1 := range a11 {
	fmt.Println(v1)
	for _, v2 := range v1 {
		fmt.Println(v2)
	}
}

数组是值类型

// 数组是值类型
b1 := [3]int{1, 2, 3} // [1 2 3]
b2 := b1              // [1 2 3] Ctrl+C Ctrl+V => 把world文档从文件夹A拷贝到文件夹B
b2[0] = 100           // b2:[100 2 3]
fmt.Println(b1, b2)   // b1:[1 2 

注意

  • 数组支持“==” “!=” 操作符,因为内存总是被初始化过的
  • [n]*T表示指针数组,*[n]T 表示数组指针

切片(slice)

和python的list 很像 就是切片只能放单一类型,python可以放任意类型

  • 切片指向了一个底层的数组。

  • 切片数据类型也时单一类型。

  • 切片的长度就是它元素的个数。

  • 长度len()求长度

  • cap() 求容量 切片的容量是底层数组从切片的第一个元素到最后一个元素的数量。通俗讲 就是 长度是切片后的长度 容量是 从切片第一个元素起,可以切片的个数。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0VZLzv2-1582107130899)(C:\Users\jys\AppData\Roaming\Typora\typora-user-images\image-20200219110342956.png)]

切片的定义

// 切片的定义
var s1 []int    // 定义一个存放int类型元素的切片
var s2 []string // 定义一个存放string类型元素的切片
fmt.Println(s1, s2)
fmt.Println(s1 == nil) // true
fmt.Println(s2 == nil) // true
s121 := []string{""}
fmt.Println("s121", s121 == nil)//s121 flase 不为空

切片的初始化

// 初始化
s1 = []int{1, 2, 3}
s2 = []string{"沙河", "张江", "平山村"}
fmt.Println(s1, s2)
fmt.Println(s1 == nil) // false
fmt.Println(s2 == nil) // false

切片的长度和容量

// 长度和容量
fmt.Printf("len(s1):%d cap(s1):%d\n", len(s1), cap(s1))
fmt.Printf("len(s2):%d cap(s2):%d\n", len(s2), cap(s2)

make

make()函数用于创建指定长度和容量的切片。

  • 格式make([]T ,size,cap)
  • T切片的元素类型,size 切片元素数量 cap 切片的容量
  • 切片的容量可以省略,省略之后 cap和size的数量相同。
s1 := make([]int, 5, 10)
fmt.Printf("s1=%v len(s1)=%d cap(s1)=%d\n", s1, len(s1), cap(s1))

s2 := make([]int, 0, 10)
fmt.Printf("s2=%v len(s2)=%d cap(s2)=%d\n", s2, len(s2), cap(s2))
//s1=[0 0 0 0 0] len(s1)=5 cap(s1)=10
//s2=[] len(s2)=0 cap(s2)=10

切片的本质

  • 切片就是一个框,框住了一块连续的内存。

  • 切片属于引用类型,真正的数据都是保存在底层数组里的。

  • 判断一个切片是否是空的,要是用len(s) == 0来判断 不应该使用s== nil判断

  • 一个nil值的切片并没有底层数组,一个nil值的切片的长度和容量都是0。但是我们不能说一个长度和容量都是0的切片一定是nil

var s1 []int         //len(s1)=0;cap(s1)=0;s1==nil
s2 := []int{}        //len(s2)=0;cap(s2)=0;s2!=nil
s3 := make([]int, 0) //len(s3)=0;cap(s3)=0;s3!=nil

append

  • 不能直接s1.append(val) 有些不爽 这方面python比较好
// 调用append函数必须用原来的切片变量接收返回值
// append追加元素,原来的底层数组放不下的时候,Go底层就会把底层数组换一个
// 必须用变量接收append的返回值
s1 = append(s1, "广州")
fmt.Printf("s1=%v len(s1)=%d cap(s1)=%d\n", s1, len(s1), cap(s1))
s1 = append(s1, "杭州", "成都")
fmt.Printf("s1=%v len(s1)=%d cap(s1)=%d\n", s1, len(s1), cap(s1))
ss := []string{"武汉", "西安", "苏州"}
// ...表示拆开 相当与python的 *  把切片差分成一个一个的元素
s1 = append(s1, ss...) 
fmt.Printf("s1=%v len(s1)=%d cap(s1)=%d\n", s1, len(s1), cap(s1))

copy

a1 := []int{1, 3, 5}
a2 := a1 // 赋值
var a3 = make([]int, 3, 3)
copy(a3, a1) // copy
fmt.Println(a1, a2, a3)
a1[0] = 100
fmt.Println(a1, a2, a3)

指针

Go语言中不存在指针操作,只需要记住两个符号:

  1. &:取地址
  2. *:根据地址取值

make和new的区别

  1. make和new都是用来申请内存的
  2. new很少用,一般用来给基本数据类型申请内存,stringint,返回的是对应类型的指针(*string、*int)。
  3. make是用来给slicemapchan申请内存的,make函数返回的的是对应的这三个类型本身

map

map也是引用类型,必须初始化之后才能使用。

  • 和python的dict 类似
  • value, ok := m1[“娜扎”] ok表示 是否有这个对应的值
  • 约定成俗用ok接收返回的布尔值
func main() {
	var m1 map[string]int
	fmt.Println(m1 == nil)        // 还没有初始化(没有在内存中开辟空间)
	m1 = make(map[string]int, 10) // 要估算好该map容量,避免在程序运行期间再动态扩容
	m1["理想"] = 18
	m1["jiwuming"] = 35

	fmt.Println(m1)
	fmt.Println(m1["理想"])
	// 约定成俗用ok接收返回的布尔值
	fmt.Println(m1["娜扎"]) // 如果不存在这个key拿到对应值类型的零值
	value, ok := m1["娜扎"]
	if !ok {
		fmt.Println("查无此key")
	} else {
		fmt.Println(value)
	}

	// map的遍历
	for k, v := range m1 {
		fmt.Println(k, v)
	}
	// 只遍历key
	for k := range m1 {
		fmt.Println(k)
	}
	// 只遍历value
	for _, v := range m1 {
		fmt.Println(v)
	}
	// 删除
	delete(m1, "jiwuming")
	fmt.Println(m1)
	delete(m1, "沙河") // 删除不存在的key
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值