『Go语言 07 切片』 声明、初始化、访问、遍历、追加、复制、传递

Go语言的切片

切片是一种基于数组的抽象数据结构,它可以动态地增长和缩小,提供了灵活且强大的功能。切片是对数组的一个引用,它不会复制数组本身,而是共享数组的存储空间。本文将介绍Go语言中切片的声明、初始化、访问、遍历、追加、复制和传递等操作。

声明切片

Go语言中声明一个切片的语法如下:

var slice_name []element_type

其中,slice_name是切片的名称,element_type是切片元素的类型。例如,下面的代码声明了一个元素类型为整数的切片:

var arr []int

如果不指定切片的元素类型,那么可以使用空接口类型(interface{})来表示任意类型的元素。例如:

var arr []interface{}

如果只想声明一个切片,而不初始化它,那么可以省略等号和花括号。例如:

var arr []int // 声明一个元素类型为整数的切片,默认值为nil

初始化切片

Go语言中初始化一个切片的语法如下:

var slice_name = []element_type{element_list}

其中,slice_name是切片的名称,element_type是切片元素的类型,element_list是用逗号分隔的元素列表。例如,下面的代码初始化了一个元素类型为字符串的切片:

var names = []string{"Alice", "Bob", "Charlie"}

如果省略了element_type,那么可以使用短变量声明(:=)来初始化一个切片。例如:

names := []string{"Alice", "Bob", "Charlie"}

如果只想初始化某些特定位置的元素,而其他位置保持默认值(零值),那么可以使用索引来指定要初始化的元素。例如:

names := []string{1:"Bob", 3:"David"} // 等价于 names := []string{"", "Bob", "", "David"}

除了使用字面量来初始化一个切片外,还可以使用内置函数make来创建一个指定长度和容量的空切片。例如:

arr := make([]int, 5) // 创建一个长度为5,容量为5,元素类型为整数的空切片,默认值为0

也可以在make函数中指定第三个参数来设置容量,但是容量不能小于长度。例如:

arr := make([]int, 5, 10) // 创建一个长度为5,容量为10,元素类型为整数的空切片,默认值为0

还可以使用内置函数len和cap来获取切片的长度和容量。例如:

fmt.Println(len(arr)) // 输出5
fmt.Println(cap(arr)) // 输出10

访问切片

Go语言中访问切片的语法如下:

slice_name[index]

其中,slice_name是切片的名称,index是要访问的元素的索引(位置)。索引从0开始,第一个元素的索引为0,第二个元素的索引为1,以此类推。例如,下面的代码访问了切片names的第二个元素:

var names = []string{"Alice", "Bob", "Charlie"}
var x string = names[1] // x = "Bob"

访问切片时,必须保证索引在切片的长度范围内,否则会发生越界错误(panic)。例如:

var names = []string{"Alice", "Bob", "Charlie"}
var x string = names[3] // panic: runtime error: index out of range [3] with length 3

遍历切片

遍历切片是指依次访问切片中的每个元素。Go语言中有两种常用的遍历切片的方法:使用for循环和使用range关键字。

使用for循环

使用for循环遍历切片的方法是利用索引来访问每个元素。例如,下面的代码遍历了切片names中的所有元素,并打印出来:

var names = []string{"Alice", "Bob", "Charlie"}
for i := 0; i < len(names); i++ {
    fmt.Println(names[i])
}

输出结果为:

Alice
Bob
Charlie

使用range关键字

使用range关键字遍历切片的方法是利用for...range循环来迭代每个元素。例如,下面的代码遍历了切片names中的所有元素,并打印出来:

var names = []string{"Alice", "Bob", "Charlie"}
for index, value := range names {
    fmt.Println(index, value)
}

输出结果为:

0 Alice
1 Bob
2 Charlie

其中,indexvalue是可以自定义的变量名,也可以用空白标识符(下划线)来忽略不需要的值。例如,如果只想获取索引,可以这样写:

var names = []string{"Alice", "Bob", "Charlie"}
for index := range names {
    fmt.Println(index)
}

输出结果为:

0
1
2

如果只想获取值,可以这样写:

var names = []string{"Alice", "Bob", "Charlie"}
for _, value := range names {
    fmt.Println(value)
}

输出结果为:

Alice
Bob
Charlie

追加切片

切片的长度是可以动态变化的,可以使用内置函数append来向切片的末尾追加一个或多个元素。例如:

var names = []string{"Alice", "Bob", "Charlie"}
names = append(names, "David") // 追加一个元素
fmt.Println(names) // 输出[Alice Bob Charlie David]
names = append(names, "Eve", "Frank") // 追加多个元素
fmt.Println(names) // 输出[Alice Bob Charlie David Eve Frank]

如果要追加另一个切片的所有元素,可以使用...来展开切片。例如:

var names = []string{"Alice", "Bob", "Charlie"}
var moreNames = []string{"David", "Eve", "Frank"}
names = append(names, moreNames...) // 追加另一个切片
fmt.Println(names) // 输出[Alice Bob Charlie David Eve Frank]

当切片的长度超过了它的容量时,append函数会自动扩容,即创建一个新的底层数组,并将原来的元素复制过来。扩容的规则是按照原来的容量的2倍进行增长,如果原来的容量为0,则增长为1。例如:

var arr []int // 声明一个空切片,长度为0,容量为0
fmt.Println(len(arr), cap(arr)) // 输出0 0
arr = append(arr, 1) // 追加一个元素,长度为1,容量为1
fmt.Println(len(arr), cap(arr)) // 输出1 1
arr = append(arr, 2) // 追加一个元素,长度为2,容量为2
fmt.Println(len(arr), cap(arr)) // 输出2 2
arr = append(arr, 3) // 追加一个元素,长度为3,容量为4(扩容)
fmt.Println(len(arr), cap(arr)) // 输出3 4
arr = append(arr, 4, 5) // 追加两个元素,长度为5,容量为4(不扩容)
fmt.Println(len(arr), cap(arr)) // 输出5 4
arr = append(arr, 6) // 追加一个元素,长度为6,容量为8(扩容)
fmt.Println(len(arr), cap(arr)) // 输出6 8

复制切片

如果要复制一个切片的所有元素到另一个切片中,可以使用内置函数copy。例如:

var names = []string{"Alice", "Bob", "Charlie"}
var copyNames = make([]string, len(names)) // 创建一个和names长度相同的空切片
copy(copyNames, names) // 复制names的所有元素到copyNames中
fmt.Println(copyNames) // 输出[Alice Bob Charlie]

copy函数的第一个参数是目标切片,第二个参数是源切片。它会按照两个切片中较短的那个进行复制。例如:

var names = []string{"Alice", "Bob", "Charlie"}
var copyNames = make([]string, 2) // 创建一个长度为2的空切片
copy(copyNames, names) // 只复制names的前两个元素到copyNames中
fmt.Println(copyNames) // 输出[Alice Bob]

如果要复制源切片中的一部分元素到目标切片中,可以先对源切片进行切割,然后再复制。例如:

var names = []string{"Alice", "Bob", "Charlie"}
var copyNames = make([]string, 2) // 创建一个长度为2的空切片
copy(copyNames, names[1:]) // 复制names的后两个元素到copyNames中
fmt.Println(copyNames) // 输出[Bob Charlie]

传递切片

Go语言中可以将一个切片作为参数传递给一个函数,也可以将一个切片作为返回值从一个函数返回。由于切片是对数组的一个引用,所以传递和返回切片都不会涉及到复制整个切片的过程,而只是复制切片的指针、长度和容量,这样可以提高性能和内存利用率。

作为参数传递

如果要将一个切片作为参数传递给一个函数,只需要在函数的定义中指定切片的元素类型。例如,下面的代码定义了一个函数getAverage,它接受一个元素类型为浮点数的切片作为参数,并返回该切片的平均值:

func getAverage(arr []float32) float32 {
    var sum float32
    for _, value := range arr {
        sum += value
    }
    return sum / float32(len(arr))
}

然后,可以在主函数中调用这个函数,并传入一个符合要求的切片:

func main() {
    var balance = []float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    var avg float32 = getAverage(balance)
    fmt.Println(avg) // 输出212.48
}

需要注意的是,由于切片是对数组的一个引用,所以在函数中对切片的修改会影响到原来的数组。例如:

func modify(arr []int) {
    arr[0] = 100 // 修改切片的第一个元素
}

func main() {
    var nums = []int{1, 2, 3}
    fmt.Println(nums) // 输出[1 2 3]
    modify(nums) // 调用modify函数,传入nums切片
    fmt.Println(nums) // 输出[100 2 3]
}

作为返回值返回

如果要将一个切片作为返回值从一个函数返回,只需要在函数的定义中指定返回值的元素类型。例如,下面的代码定义了一个函数getSlice,它返回一个元素类型为整数的切片:

func getSlice() []int {
    var arr []int
    for i := 0; i < 5; i++ {
        arr = append(arr, i+1)
    }
    return arr
}

然后,可以在主函数中调用这个函数,并接收返回的切片:

func main() {
    var arr []int = getSlice()
    fmt.Println(arr) // 输出[1 2 3 4 5]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值