go 切片(创建、nil切片、空切片、切片拷贝)

本文详细介绍了Go语言中切片的概念,包括切片的数据结构、如何创建切片、nil切片与空切片的区别,以及切片的初始化。此外,还探讨了切片的append函数和copy函数的使用,展示了切片在内存管理和数据操作中的特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是切片

1.切片就是一个“动态”数组,即切片的长度是可以伸缩的。其数据结构是一个结构体,包含三个字段,指向数组的指针、长度、容量。

type slice struct {
    array unsafe.Pointer  //一个指向数组的指针
    len   int
    cap   int
}

2.切片的指针指向某个数组,所以它是引用类型。

3.代码验证切片是引用类型

package main

import "fmt"

//传入切片
func change(s []string) { 
	s[1] = "c++"
}

func main() {
	lang := []string{"golang","java","php","js"}
	fmt.Println(lang[1])  //java
	change(lang)
	fmt.Println(lang[1])  //c++
}

二、切片创建

1.申明并创建(分两步:1-声明  2-make初始化)

var s1 []int           //申明
s1 = make([]int , 2)   //分配内存

2.直接make()创建

var s []int = make([]int , 6)

3. 推导make创建

s := make([]int , 6)

4.从数组中截取

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

三、nil切片和空切片

1.nil切片:声明为切片,但是没有分配内存。切片的指针是nil

注意:只有声明的切片才会产生nil切片,通过推导或数组截取的切片都是指针有指向的。

var s []int

2.空切片:切片指针指向了一个数组内存地址,但是数组是空的。 空切片有两种方式产生,如下:

s1 := []int{}   //1.空切片,没有任何元素

s2 := make( []int, 0)  //2.make 切片,没有任何元素

3.nil切片和空切片的本质区别就是: nil切片没有分配内存,空切片是有分配内存但底层指向的是一个空数组 

 四、用数组 和 切片  初始化切片

1.初始化

arr := [5]int{1, 2, 3, 4, 5} //数组

s1 := arr[:]                 //数组初始化切片

s2 := s1[:]                  //切片s1初始化切片s2

2.截取操作符 [ startIndex : endIndex ]

注意截取中的startIndex、endIndex 指的是数组或切片的下标位置,startIndex是截取时开始的位置,endIndex是结束的位置而不包含结束位置的元素

 2.数组截取初始化切片实例

全局变量:
var arr = [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} //这是一个数组
var slice0 []int = arr[start:end] 
var slice1 []int = arr[:end]        
var slice2 []int = arr[start:]        
var slice3 []int = arr[:] 
var slice4 = arr[:len(arr)-1]      //去掉切片的最后一个元素
局部变量:
arr2 := [...]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}  //这是一个数组
slice5 := arr[start:end]
slice6 := arr[:end]        
slice7 := arr[start:]     
slice8 := arr[:]  
slice9 := arr[:len(arr)-1] //去掉切片的最后一个元素

五、操作切片的函数  append()   copy()

1.切片尾部追加元素 append()

注意:如下合并其他切片时,需要   ... 来展开切片

data := [...]int{0, 1, 2, 3, 4, 10: 0} //数组
s  := data[:]
s2 := data[1:5]
s = append(s,100)         //1.追加1个元素
s = append(s,200,300,400) //2.追加多个元素
s = append(s,s2...)       //3.合并其他切片
                     

2.切片的拷贝:切片分为 1-浅拷贝  2-深拷贝(copy())

2.1 浅拷贝 :源切片和目的切片共享同一底层数组空间

  slice1 := make([]int, 5, 5)
  slice2 := slice1
  slice1[1] = 1
  fmt.Println(slice1) //[0 1 0 0 0]
  fmt.Println(slice2) //[0 1 0 0 0]

2.2深拷贝:源切片和目的切片各自都有彼此独立的底层数组空间, 

注意:copy(s1,s2),是将源切片的内容拷贝到目的切片中,即将s2元素拷贝到s1中,如果s1长度3,s2的长度5,那么复制到s2则将前三个元素覆盖到s1的三个元素上。

    slice1 := make([]int, 5, 5)
	slice1[0] = 9
	fmt.Println(slice1)
	slice2 := make([]int, 4, 4)
	slice3 := make([]int, 5, 5)
	fmt.Println(slice2)
	fmt.Println(slice3)
	//拷贝
	fmt.Println(copy(slice2, slice1)) //4
	fmt.Println(copy(slice3, slice1)) //5
	//独立修改
	slice2[1] = 2
	slice3[1] = 3
	fmt.Println(slice1) //[9 0 0 0 0 0]
	fmt.Println(slice2) //[9 2 0 0]
	fmt.Println(slice3) //[9 3 0 0 0]

结果:

[9 0 0 0 0]
[0 0 0 0]
[0 0 0 0 0]
4
5
[9 0 0 0 0]
[9 2 0 0]
[9 3 0 0 0]

<think>好的,我现在需要回答用户关于Go语言切片用法的问题。首先,我要确保自己正确理解切片的概念,以及它在Go中的常见操作。让我先回忆一下相关知识。 切片(Slice)在Go中是动态数组,提供更灵活的数据处理方式。与数组不同,切片的长度不固定,可以动态增加或减少。这一点我记得对吗?对的,数组有固定长度,而切片是对数组的抽象,所以更灵活。 接下来,用户可能需要知道切片的基本声明和初始化方法。比如,使用make函数创建切片,或者通过数组来生成切片。例如: var s []int s := make([]int, 5) 或者从数组: arr := [3]int{1,2,3} s := arr[:] 这些例子是否正确?是的,用户可能需要这些基本操作。 然后,切片的常用操作,比如添加元素、截取部分、复制等。append函数是关键,用于动态添加元素。需要注意append可能引发底层数组的重新分配,这点需要提到吗?用户可能需要了解切片的自动扩容机制。 比如: s := []int{1,2,3} s = append(s, 4) 这样s的长度变为4。正确。另外,截取切片的部分可以用s[start:end],例如s[1:3],但需要注意左闭右开区间。这点容易出错,应该强调。 还有,切片的长度和容量,len()和cap()函数的区别。长度是当前元素数量,容量是底层数组的最大长度。这需要解释清楚,避免混淆。 另外,切片的复制,使用copy函数,可以避免共享底层数组的问题。比如: s1 := []int{1,2,3} s2 := make([]int, len(s1)) copy(s2, s1) 这样修改s2不会影响s1。这点对用户来说可能重要,特别是处理数据时需要注意引用问题。 还有,切片的遍历,使用for循环配合range关键字,例如: for index, value := range s { // 处理 } 这些是不是常见的用法?是的,应该包含。 还需要注意切片的零值是nil,判断切片是否为空应该用len(s) == 0,而不是s == nil,因为可能存在非nil但长度为0的情况。这点可能容易被忽视,需要提醒用户。 有没有其他需要注意的地方?比如切片作为函数参数传递时是引用类型,修改会影响原数据。用户可能需要注意这一点,以免意外修改。 总结一下,我需要组织这些点,分步骤介绍,结构清晰,简短但涵盖主要用法。可能需要分点说明:声明初始化、基本操作(增删改查)、长度容量、注意事项等。同时确保使用中文,避免术语错误,并保持例子简洁,符合用户要求的简短说明。</think>Go语言切片(Slice)是动态数组的实现,核心用法如下: --- ### 一、声明与初始化 ```go // 1. 直接声明 var s1 []int // 初始为nil s2 := []int{1, 2, 3} // 初始化值 // 2. 通过make创建 s3 := make([]int, 3) // 长度3,容量3 s4 := make([]int, 2, 5) // 长度2,容量5 // 3. 从数组/切片截取 arr := [5]int{0,1,2,3,4} s5 := arr[1:4] // [1,2,3] (含起始索引,不含结束索引) ``` --- ### 二、核心操作 1. **添加元素** ```go s := []int{1,2} s = append(s, 3) // [1,2,3] s = append(s, 4,5) // [1,2,3,4,5] ``` 2. **截取子切片** ```go s := []int{0,1,2,3,4} sub := s[1:3] // [1,2] (索引1到2) ``` 3. **复制切片** ```go src := []int{1,2,3} dst := make([]int, len(src)) copy(dst, src) // 深拷贝,修改dst不影响src ``` 4. **遍历** ```go for i, v := range s { fmt.Println(i, v) // 索引+值 } ``` --- ### 三、长度与容量 - **长度**:当前元素数量(`len(s)`) - **容量**:底层数组的最大元素数(`cap(s)`) - **扩容**:当`append`超过容量时,自动分配新数组(通常容量翻倍) --- ### 四、注意事项 1. 切片是**引用类型**,多个切片可能共享底层数组 2. 判断空切片应使用 `len(s) == 0`,而非 `s == nil` 3. 可通过 `s[:0]` 清空元素(保留底层数组) --- 掌握这些操作即可应对90%的切片使用场景!
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值