Go基础之切片

Talk is cheap, show me the code:)

代码:

package main

import (
	"fmt"
)

// func main() {
// 	var x = [3]int{1, 2, 3}
// 	fmt.Println(arraySum(x))
// }

// func arraySum(x [3]int) int{
// 	sum := 0
// 	for i := 0; i < len(x); i++ {
// 		sum += x[i]
// 	}
// 	return sum
// }

// 切片(slice )
func main() {
	// 声明切片类型
	var a []string //切片声明但没有初始化则值为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

	var b = []int{}             // 声明一个整型切片并初始化,值不为nil
	var c = []bool{false, true} // 声明一个布尔切片并初始化
	var d = []bool{false, true} // 声明一个布尔切片并初始化
	fmt.Println(a)
	fmt.Println(b)
	fmt.Println(c)
	fmt.Println(d)
	fmt.Println(a == nil) // true
	fmt.Println(b == nil) // false
	fmt.Println(d == nil) // false
	// fmt.Println(c == d)		//切片是引用类型,不支持直接比较
	b = []int{1, 2, 3}
	fmt.Println(b == nil)
	a = []string{"北京", "上海", "武汉", "深圳"}

	// 打印长度和容量
	fmt.Printf("len(a):%d cap(a):%d\n", len(a), cap(a))
	fmt.Printf("len(b):%d cap(b):%d\n", len(b), cap(b))

	// 2.由数组得到切片
	a1 := [...]int{1, 3, 5, 7, 9, 11, 13}
	s3 := a1[0:4] // 1 3 5 7, 基于一个数组切割,左包含右不包含
	fmt.Println(s3)
	s4 := a1[1:6]
	fmt.Println(s4)
	s5 := a1[:4] // => [0:4] [1 3 5 7]
	s6 := a1[3:] // => [3:len(a1)] [7 9 11 13]
	s7 := a1[:]  // => [0:len(a1)]
	fmt.Println(s5, s6, s7)

	// 切片的长度和容量
	fmt.Printf("len(s5):%d cap(s5):%d\n", len(s5), cap(s5)) // len(s5):4 cap(s5):7
	fmt.Printf("len(s6):%d cap(s6):%d\n", len(s6), cap(s6)) // len(s6):4 cap(s6):4
	// 直接声明并初始化一个切片时,Go底层也会先分配一个数组

	// 切片再切片,切片在切片的容量还是根据底层的数组(从切片的第一个元素开始)来计算
	s8 := s6[3:]                                            // [13]
	fmt.Printf("len(s8):%d cap(s8):%d\n", len(s8), cap(s8)) // len(s8):1 cap(s8):1
	s9 := s5[1:]                                            // [3 5 7]
	fmt.Printf("len(s9):%d cap(s9):%d\n", len(s9), cap(s9)) // len(s9):3 cap(s9):6

	// 切片是引用类型,都指向了底层的一个数组
	fmt.Println("s6:", s6)
	a1[len(a1)-1] = 1300
	fmt.Println("s6:", s6)
	fmt.Println("s8:", s8)

	// 上面都是通过数组创建切片,如果需要动态地创建切片,需要使用内置的make函数
	// make函数的容量值省略默认是和长度相同的
	s10 := make([]int, 5, 10) // make([]T, size, cap)
	fmt.Printf("s10=%v len(s10)=%d cap(s10)=%d\n", s10, len(s10), cap(s10))
	s11 := make([]int, 0, 10)
	fmt.Printf("s11=%v len(s11)=%d cap(s11)=%d\n", s11, len(s11), cap(s11))

	// 切片扩容
	// append函数将元素追加到切片的最后并返回该切片
	// 切片numSlice的容量按照1 2 4 8 16自动扩容,每次扩容后都是扩容前的2倍,此时切片指向的底层数组就会更换
	var numSlice []int
	for i := 0; i < 10; i++ {
		numSlice = append(numSlice, i)
		fmt.Printf("%v len:%d cap:%d ptr:%p\n", numSlice, len(numSlice), cap(numSlice), numSlice)
	}

	var citySlice []string
	citySlice = []string{"武汉", "黄冈", "北京", "深圳"}
	fmt.Println(citySlice)
	// append可以添加一个元素
	citySlice = append(citySlice, "上海")
	fmt.Println(citySlice)
	// append添加多个元素
	citySlice = append(citySlice, "杭州", "广州")
	// append添加切片
	tailSlice := []string{"西安", "成都"}
	// ...表示拆分,即将前面的切片tailSlice拆开
	citySlice = append(citySlice, tailSlice...)
	fmt.Println(citySlice)

	// 切片的扩容策略
	// 如果新申请的容量大于2倍的旧容量,最终申请的容量就是新申请的容量
	// 否则,如果旧切片的长度小于1024,则最终容量就是旧容量的两倍
	// 如果旧切片长度大于1024,则最终容量从旧容量开始循环增加原来的1/4

	// 使用copy函数复制切片
	srcSlice := []int{1, 2, 3, 4, 5}
	destSlice := make([]int, 5, 5)
	copy(destSlice, srcSlice)
	fmt.Printf("before mutual: %v\n", srcSlice)
	fmt.Printf("before mutual: %v\n", destSlice)
	srcSlice[4] = 1000
	fmt.Printf("after mutual: %v\n", srcSlice)
	fmt.Printf("after mutual: %v\n", destSlice)

	// Go语言没有删除切片元素的专用方法,可使用切片本身的特性来删除元素
	origSlice := []int{1, 3, 5}
	origSlice = append(origSlice[:1], origSlice[2:]...) // len(origSlice)=2 cap(origSlice)=3
	fmt.Printf("origSlice:%v len(origSlice):%d cap(origSlice):%d\n", origSlice, len(origSlice), cap(origSlice))

	// 一个易混淆的点:切片不占用内存
	x1 := [...]int{1, 3, 5}
	ss1 := x1[:]
	fmt.Println(ss1, len(ss1), cap(ss1))
	// 切片不保存具体的值,切片对应一个底层数组,底层数组占用一块连续内存
	ss1 = append(ss1[:1], ss1[2:]...)
	fmt.Println(x1) //x1:[1 5 5]
	// // 第二种情况
	// x1 := [...]int{1, 3, 5}
	// ss1 := x1[:]
	// fmt.Printf("x1:%p, ss1:%p\n", &x1[0], ss1)
	// ss2 := []int{2, 4, 6}
	// ss1 = append(ss1[:1], ss2...)
	// fmt.Println(ss1, x1)
	// fmt.Printf("x1:%p, ss1:%p\n", &x1[0], ss1)

	// 切片的练习题
	var aa = make([]int, 5, 10)
	for ii := 0; ii < 10; ii++ {
		aa = append(aa, ii)
	}
	fmt.Println(aa) // [0 0 0 0 0 1 2 3 4 5 6 7 8 9]

}

运行结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值