[Go语言tips03]数组与切片与...语法糖

0. 引言

C中只有数组的概念,没有切片的概念;Python中只有切片的概念,没有数组的概念;Go语言同时拥有数组和切片的概念,这两者看起来没什么区别都直接通过[x]int来使用,但实际上有很多不同的点。

1. 数组

1.1 什么是数组及其类型

数组,一言以蔽之:定长的同类型数据集合

即数组的长度是固定的且数组内的元素类型相同。关键的点就在于这个长度是否是固定。因为在Go语言中数组类型是包括长度以及类型,如:

var a[100]int // 数据类型为 [100]int
var b[365]int // 数据类型为 [365]int

要知道,不同类型之间是不能通过=赋值的,也就是说在上面的情况下,若添加上一句a = b会发生编译错误。

1.2 “不定”数组及其类型

特殊的,如果不确定数组的长度,可以使用Go语言的...语法糖。通过以下操作来声明一个数组:x := [...]int{11,22} ,此时x的数据类型为[2]int

注意在使用[...]int来定义一个不确定长度的数组时必须直接赋值,因为在本质上通过语法糖来定义的数组虽然可以存放任意个数,但仍需要确定长度(定义结束即为确定长度)。

如果没有直接把数据传入var m = [...]int{}之中的m的数据类型就是[],此时这个变量m就毫无意义了;

1.3 数组的拷贝(深拷贝)

数组只有在数据类型相同的情况下才能进行传递(都是[2]int或者[5]int ……),并且数组是值传递会进行深拷贝,也就是说被赋值的变量地址与赋值的变量不同。

a := [6]int{1,2,3,4,5,6}
x := a
x[0] = 999
fmt.Println(a) 
fmt.Println(x)
/*
[1 2 3 4 5 6]
[999 2 3 4 5 6]
*/

2. 切片

2.1 什么是切片及其类型

切片和数组最大的区别就是长度不固定,并且切片的数据类型一定是[]int

2.2 切片的拷贝(浅拷贝)

切片最简便的地方就是可以通过x[start:end]来进行一个截取(前闭后开),其中start默认为0,end默认为len(x)。

需要注意的一点是切片是浅拷贝传递因此s2 := s[1:3]实际上s2中这些数据所存储的空间和s中的这几个元素是相同的,也就是说我改变s2中的值同样也会改变s,反之亦然。

变化的是,s2的下标是重新编排的s[1]对应s2[0],s[2]对应s2[1] (前闭后开因此只有两个)……s2只有两个元素(s[1],s[2])所以他不能够使用s2[2] (越界)。

package main

import "fmt"

func main() {
	a := []int{1, 2, 3, 4, 5, 6}
	b := a[1:3]
	b[0] = 999
	fmt.Println(a)
	fmt.Println(b)
}
/*
[1 999 3 4 5 6]
[999 3]
*/

2.3 切片的追加及深拷贝

package main

import "fmt"

func main() {
	a := []int{1, 2, 3}
	b := []int{4, 5, 6}
	c := make([]int, 0)

	a = append(a, b...)
	c = append(c, a...)

	b[0] = 444
	a[0] = 111

	fmt.Println(a) // b修改不影响a
	fmt.Println(b) 
	fmt.Println(c) // a修改不影响c
}
/*
[111 2 3 4 5 6]
[444 5 6]
[1 2 3 4 5 6]
*/

由此可见append是直接进行值的传递的。

3. ...语法糖

3.1 什么是语法糖

以下是维基百科中的解释:

语法糖(英语:Syntactic sugar),指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。语法糖让程序更加简洁,有更高的可读性。

3.2 应用于不定参数

package main

import "fmt"

func main() {
	Printer(1, 2, 3)
	Printer(4, 5)
}

func Printer(x ...int) {
	fmt.Printf("%T\n", x)
	for _, v := range x {
		fmt.Println(v)
	}
}
/*
[]int
1
2
3
[]int
4
5
*/

可以通过上面的测试得知,通过...语法糖获得的参数组是一个切片类型。

3.3 应用于切片传递

package main

import "fmt"

func main() {
	a := []int{1, 2, 3}
	b := []int{4}

	b = append(b, a[1:3]...)

	fmt.Println(a)
	fmt.Println(b)
}
/*
[1 2 3]
[4 2 3]
*/

由此可见,...语法糖多用于切片的操作,它是放在变量名后面的。当需要append多个元素的时候就可以使用该语法糖进行操作。

posted @   WtcSky  阅读(52)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示