go基础篇之二

本文介绍了Go语言中的切片(Slice)概念,它是一个动态数组,提供了长度和容量的概念。文中通过示例展示了切片的初始化、截取、追加和删除操作,并探讨了切片的扩容原理。在扩容过程中,当新容量大于旧容量的两倍时,会直接使用新容量,否则根据旧切片长度进行逐步增长策略。
摘要由CSDN通过智能技术生成

一、切片

切片(Slice)是一个拥有相同类型元素的可变长度的序列。它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。

切片是一个引用类型,它的内部结构包含地址长度容量。切片一般用于快速地操作一块数据集合。

二、切片的实战

package main

import "fmt"

func main() {

	//切片 切片是一种动态数组,比数组操作起来更加方便,长度不固定,可以动态的追加和删除

	/**
	len()  cap() 返回的结果可以相同或者不同
	len() :指的是长度
	cap() :指的是切片的容量
	 */

	// nil 空的切片
	var s1 [] int

	fmt.Print(s1)

	fmt.Printf("len=%d cap=%d slice=%v", len(s1), cap(s1), s1)
	// 空切片

	var s2 = [] int{}

	fmt.Printf("len = %d cap =%d slice=%v", len(s2), len(s2), s2)

	var s3 = [] int{1, 2, 3, 4, 5}

	fmt.Printf("len =%d cap =%d slice=%v", len(s3), len(s3), s3)
    
    // 使用make 函数构造切片
	var s4 [] int = make([] int, 4, 5)

	fmt.Printf("len =%d cap =%d slice=%v", len(s4), len(s4), s4)

	s5 := make([] uint8, 2, 5)
	fmt.Printf("len=%d cap=%d slice=%v", len(s5), cap(s5), s5)

	// 截取切片

	sli := [] int{1, 2, 3, 4, 5}

	fmt.Print("\n==========我是分割线=============")

	fmt.Printf("\n len=%d cap=%d slice=%v \n", len(sli), cap(sli), sli)

	fmt.Print("sli[1] == ",sli[1] ,"\n")

	fmt.Println("sli[1] == ",sli[1] ,"\n")

	fmt.Println("sli[:] ==",sli[:],"\n")

	// 截取前面1位
	fmt.Println("sli[1:] == ",sli[1:])

	// 获取数组中前两位
	fmt.Println("sli[:2] == ",sli[:2])

	// 获取数组区间值
	fmt.Println("sli[0:3] == ",sli[0:3])


	fmt.Println("sli[0:2:4] == ",sli[0:2:4])

	fmt.Printf("len = %d cap=%d slice=%v \n",len(sli[0:2:4]),cap(sli[0:2:4]),sli[0:2:4])



	//追加切片

	sli = append(sli,6)

	fmt.Println("sli == ",sli)


	sli = append(sli,6,7,8)

	fmt.Print("sli ==",sli,"\n")



	//删除切片

	// 删除尾部一个元素
	fmt.Print("sli[:len(sli) -1] == ",sli[:len(sli) -1],"\n")


	// 删除头部2个元素
	fmt.Println("sli[2:] == ",sli[2:])

	// 删除中间2个元素
	arr2 := [] int{1, 2, 3, 4, 5,6,7,8}

	arr2 = append(arr2[:1],arr2[1+2:]...)

	fmt.Println("删除中间元素",arr2)


	arr3 := [] int{1, 2, 3, 4, 5,6,7,8}

	arr3 = append(arr3[:2],arr3[1+3:]...)

	fmt.Println("删除中间元素",arr3)


	}

三、切片的原理

切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)。

我们可以根据下面这个例子来看下:

有一个数组 a := [8]int{0, 1, 2, 3, 4, 5, 6, 7},切片s1 := a[:5]

 

四、切片的扩容

看下面的源码

newcap := old.cap
doublecap := newcap + newcap
if cap > doublecap {
	newcap = cap
} else {
	if old.len < 1024 {
		newcap = doublecap
	} else {
		// Check 0 < newcap to detect overflow
		// and prevent an infinite loop.
		for 0 < newcap && newcap < cap {
			newcap += newcap / 4
		}
		// Set newcap to the requested cap when
		// the newcap calculation overflowed.
		if newcap <= 0 {
			newcap = cap
		}
	}
}
  • 首先判断,如果新申请容量(cap)大于2倍的旧容量(old.cap),最终容量(newcap)就是新申请的容量(cap)。
  • 否则判断,如果旧切片的长度小于1024,则最终容量(newcap)就是旧容量(old.cap)的两倍,即(newcap=doublecap),
  • 否则判断,如果旧切片长度大于等于1024,则最终容量(newcap)从旧容量(old.cap)开始循环增加原来的1/4,即(newcap=old.cap,for {newcap += newcap/4})直到最终容量(newcap)大于等于新申请的容量(cap),即(newcap >= cap)
  • 如果最终容量(cap)计算值溢出,则最终容量(cap)就是新申请容量(cap)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值