Go 语言中切片的访问

        在定义数组时,我们不但给出了数据类型,还规定了数组的大小。这意味着一旦创建了数组,就不能改变它的大小。不过某些情况下,固定长度的数组可能会带来不便。

        Go 通过使用切片支持可变大小的数组结构。与数组不同,切片数据类型不依赖其长度,因此切片是一个动态而强大的工具,比数组更灵活。本质上,切片是数组中值的子集。

1. 切片的工作原理

        切片是建立在数组类型之上的抽象。这意味着它允许使用与数组相同的逻辑,但具有更强大的功能和灵活性。

        切片是数组的一部分;也就是说,可以创建一个数组,然后再创建一个切片,切片只引用该数组中的一些元素。由于数组中的每个元素必须是相同的数据类型,因此切片中的每个元素也必须是相同的数据类型。

        切片包括指向数组中的元素的指针、切片的长度以及它的容量(切片能够容纳的最大元素数量,这取决于底层数组的大小)。

 2. 对数组进行切片

        为更好地理解切片和数组之间的关系,可以看一个例子。在这个例子中,首先创建一个包含 7 个整数的数组,然后创建该数组的一个切片。代码如下所示,它通过使用原始数组位置 0~4 的值来创建一个切片。

package main

import (
	"fmt"
	"reflect"
)

func main() {
	numbers := [7]int{0, 1, 2, 5, 798, 43, 78}
	fmt.Println("array value:", numbers)
	fmt.Println("array type:", reflect.TypeOf(numbers))

	s := numbers[0:4]
	fmt.Println("slice value:", s)
	fmt.Println("slice type:", reflect.TypeOf(s))
}

这个代码清单首先定义了一个名为 numbers 的数组(它包含7个 int 类型的元素),并在声明时进行了赋值。然后打印出这个数组,接着使用 reflect 包中的 TypeOf 方法来证明 number 确实是一个数组。

array value: [0 1 2 5 798 43 78]
array type: [7]int

下面的代码将 s 声明为 numbers 数组的一个切片。

s := numbers[0:4]

该切片包括指针 0 (引用数组中的第一个元素)和接下来的 3个元素。定义切片后,再使用两条打印语句。这一次打印的是 s 的值和类型。

slice value: [0 1 2 5]
slice type: []int

注意,在输出中数组类型显式包含数组的大小 (7),而切片类型则不包含大小。上述代码清单的完整输出如下:

array value: [0 1 2 5 798 43 78]
array type: [7]int
slice value: [0 1 2 5]
slice type: []int
2.1 使用 len 和 cap 

        要计算切片的长度和容量,可以使用 len 和 cap 函数。下面的代码演示了如何使用这个函数来确定切片的长度和容量。

package main

import (
	"fmt"
)

func main() {
	numbers := [7]int{0, 1, 2, 5, 798, 43, 78}
	fmt.Println(numbers)

	mySlice := numbers[1:5]
	fmt.Println(mySlice)

	fmt.Println("Length of slice:", len(mySlice))
	fmt.Println("Slice capacity:", cap(mySlice))
}

在本例中,创建了一个名为 mySlice 的切片,它从数组的第二个元素开始,包含从该点开始的 4 个元素。

  • 指针为 1,因为它是原始数组中包含的第二个元素
  • 长度是 4,因为包含了 4 个元素。从数组的索引位置 1 开始,到索引位置 5。 
  • 切片的容量是由数组本身的大小决定的。在这个例子中,由于从索引位置 1 开始切片,因此排除了数组中的第一个元素。因为该数组包含 7 个元素,所以该切片的容量为 6 。

上述代码清单的输出结果如下所示:

[0 1 2 5 798 43 78]
[1 2 5 798]
Length of slice: 4
Slice capacity: 6
2.2 使用快捷方式

        可以使用快捷符号来定义切片的大小和元素,这样可以更简洁。基本的语法包括指针和长度,同时 Go 语言也会为它们提供默认值。

3. 改变切片的大小

        由于切片不像数组那样由其大小定义,因此可以从原始数组创建不同长度的切片。在下面代码中,使用 numbers 数组中的 4 个元素创建了一个名为 s 的切片。然后,将该切片替换为长度与原始切片容量相同的切片。

4. 对切片进行迭代

        可以使用 for 循环来迭代切片中的元素。下面的代码创建一个数组,然后创建一个基于该数组的切片。最后使用 for 循环来打印切片的值。

5. make 函数

        切片总是依赖数组,因此切片中的每个元素必须具有相同的数据类型。另外,虽然在声明时可以定义切片的初始大小,但切片的大小并非其定义的固有部分。

        两个或多个切片可以引用相同的数组。如果将一个切片分配给另一个切片,那么这两个切片将引用同一个数组,即便没有明确指出引用自哪个数组。

        Go 语言还允许使用内置的 make 函数直接创建切片,而无须先创建一个数组。当使用 make 函数时,编译器会在内部创建一个数组,然后创建一个引用该数组的切片,如下面代码所示:

 6. 使用 var 创建切片变量

        我们也可以使用 var 来创建切片变量,语法如下:

var variableName []dataType

        在下面的代码清单中,创建了一个空的切片变量,然后显示了该切片及其类型。这可以使用 var 来实现。

7. 处理切片元素

        切片虽然显式或隐式地依赖数组,但其中每个元素都可以使用基于该切片的索引值进行标识,其中第一个元素的索引值为 0 ,而不管该元素在原始数组中的索引值为何。

7.1 替换切片中的元素

        通过该问切片中的单个元素,可以对它们进行更改。这包括替换切片中单个元素的值,如下面代码清单所示:

7.2 使用空切片

值得一提的是,如果切片为空,则无法使用索引向其中添加元素。

7.3 使用切片的部分元素
7.4 在切片中使用 range 

8. 使用 append 函数向切片追加值

        虽然不能将值追加到数组,但是可以将值追加到切片中。使用 append 函数可以在切片的未尾添加一个新元素。如果切片是空的,新元素将被放置在索引 0 处。如果切片不为空,append 会将元素添加到第一个可用位置。下面代码清单演示了如何创建一个名为  s 的空切片,然后向其中添加两个元素。

9. 复制切片

        可以使用 copy 函数将一个切片的内容复制到另一个切片中。在下面的代码中,创建了一个包含两个元素的切片和一个空切片。然后将第一个切片中的元素复制到第二个切片中。

10.使用 new 关键字创建切片

        我们可以使用 new 关键字创建切片。这种情况下,可以使用如下语法:

var newSlice = new ([capacity] type) (startingElement:length)

11.从切片中删除元素

        Go 中没有一个内置函数允许从切片中轻松删除元素,但你可以使用重新切片的概念。也就是说,从原始切片构建一个新切片,同时删除不想要或不需要的元素。

        让我们首先考虑下面的函数 RemoveIndex 。该函数接收一个 inSlice 切片 和一个索引(要删除元素的索引)作为输入,并返回一个新切片。

func RemoveIndex(inSlice []int, index int) []int {
    return append(inSlice[:index],inSlice[index+1:]...)
}

        在这个函数中,只需要使用 append 函数来连接两个切片。第一个切片是 inSlice[:index],它将包含要删除的元素之前的所有元素。第二个切片是 inSlice[index+1:],它包含要删除的元素之后的所有元素。然后通过 append 函数将这两个切片连接起来,并将连接后的结果作为函数的返回值。

  • 11
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mindfulness code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值