首页 >后端开发 >Golang >切片:Go 的骨干!

切片:Go 的骨干!

Patricia Arquette
Patricia Arquette原创
2024-11-16 14:09:03271浏览

Slices: The Backbone of Go!

好吧,让我们深入了解 Go 最通用和最重要的功能之一 - 切片。如果您来自另一种语言,您可能会认为切片与数组类似。是的,它们确实有一些相似之处,但是切片带来了更多的功能、灵活性和 Go 特有的魔力! ?

到底什么是切片? ?

在 Go 中,切片是一种允许您处理元素列表(如数组)的类型,但它们是动态的,这意味着它们可以根据需要增长和缩小。无需像使用数组那样预先指定固定长度。它们背后有阵列支持,但你可以获得更多的控制权。将它们视为数组更酷、更灵活的兄弟。

所以,Go 中的切片实际上是底层数组上的一个“窗口”。您可以通过增大或缩小该窗口来更改其大小,这就像切一块蛋糕一样顺利。 ?

创建切片?
创建切片非常简单:

// Using a literal
numbers := []int{1, 2, 3, 4, 5}

// Using the make function
sliceOfStrings := make([]string, 5) // a slice of 5 strings, each 

初始化为空字符串
使用 make,您可以告诉 Go 创建一个特定长度的切片,但由它为您管理的数组提供支持。所以你不需要担心内存分配细节。 ?

长度和容量?

切片中的两个关键概念是长度和容量。长度是切片中当前元素的数量,而容量是在需要调整大小之前可以容纳的元素总数。

numbers := []int{1, 2, 3}
fmt.Println(len(numbers)) // 3
fmt.Println(cap(numbers)) // 3 (same as length here)

当您开始追加项目时,Go 会在填满时将容量加倍,因此您不必担心会达到上限。

numbers = append(numbers, 4)
fmt.Println(len(numbers)) // 4
fmt.Println(cap(numbers)) // probably 6 now, depending on Go’s growth 

图案
附加到切片:Go 的内置魔法?✨
使用 Go 的追加函数向切片添加元素就像做馅饼一样简单。您可以一次添加一个或多个元素,Go 将为您处理所有大小调整和内存操作。

numbers := []int{1, 2, 3}
numbers = append(numbers, 4, 5, 6) // Adding multiple elements at once
fmt.Println(numbers) // [1 2 3 4 5 6]

这种自动调整大小的功能使切片变得非常方便,尤其是当您不知道列表将有多大时。

切一片??

Go 中的切片实际上是事情变得非常有趣的地方。您可以创建现有切片的“子切片”,而无需复制元素。

numbers := []int{10, 20, 30, 40, 50}
subSlice := numbers[1:4] // Just takes a "slice" of the original slice
fmt.Println(subSlice) // [20 30 40]

在数字[1:4]中,第一个索引(1)包含在内,最后一个索引(4)不包含。您最终会得到位于位置 1、2 和 3 的元素,但不是 4。

这个子切片仍然与原始切片共享相同的底层数组,因此对一个子切片的更改将影响另一个:

subSlice[0] = 25
fmt.Println(numbers) // [10 25 30 40 50]
fmt.Println(subSlice) // [25 30 40]

为了避免任何意外的更改,您可以使用复制来创建切片的独立版本:

// Using a literal
numbers := []int{1, 2, 3, 4, 5}

// Using the make function
sliceOfStrings := make([]string, 5) // a slice of 5 strings, each 

通过附加更改容量?

如果您需要一个大于其当前容量的切片,append 将在后台自动创建一个新的、更大的数组并复制所有内容。这是非常高效的,也是使切片变得很棒的重要原因。当追加创建新数组时,它会分配之前容量的两倍 - 给您增长的空间!

切片和内存效率?

这里有一个 Go 的小秘密:虽然切片非常强大,但如果你不小心,它有时会导致内存泄漏。由于切片引用相同的底层数组,因此即使您只使用其中的一小部分,该数组也可能保留在内存中。

例如:

numbers := []int{1, 2, 3}
fmt.Println(len(numbers)) // 3
fmt.Println(cap(numbers)) // 3 (same as length here)

在这种情况下,最好使用复制来创建一个真正独立的切片,仅包含您需要的数据,从而释放其余内存。

numbers = append(numbers, 4)
fmt.Println(len(numbers)) // 4
fmt.Println(cap(numbers)) // probably 6 now, depending on Go’s growth 

多维切片??

需要多个维度?您也可以创建多维切片!这对于网格或表格之类的东西非常方便。只需声明一个切片:

numbers := []int{1, 2, 3}
numbers = append(numbers, 4, 5, 6) // Adding multiple elements at once
fmt.Println(numbers) // [1 2 3 4 5 6]

每个“行”本身就是一个切片,因此您可以根据需要独立生长它们。

numbers := []int{10, 20, 30, 40, 50}
subSlice := numbers[1:4] // Just takes a "slice" of the original slice
fmt.Println(subSlice) // [20 30 40]

零切片?

nil 切片只是一个尚未初始化的切片。它的长度和容量为零,但仍然可以与诸如追加之类的函数一起使用而不会惊慌。

subSlice[0] = 25
fmt.Println(numbers) // [10 25 30 40 50]
fmt.Println(subSlice) // [25 30 40]

当你追加到一个 nil 切片时,Go 会自动为你初始化它。这是一个巧妙的技巧,需要你袖手旁观。

陷阱和最佳实践?
注意共享内存:记住,切片与原始数组共享内存。这对于性能来说非常有用,但在对大型数组进行切片时要小心,以避免在内存中保留不需要的数据。

注意调整大小:当你追加时,如果当前容量已满,Go 可能需要创建一个新的底层数组。这比进行许多小的调整大小更有效,但如果您正在处理大型数据集,请注意开销。

避免过早优化:Go 使用切片自动处理大量内存分配和调整大小。通常,尝试对这些细节进行微观管理最终可能会使您的代码变得更加混乱且效率降低。相信 Go 的切片机制在大多数情况下都能做正确的事情。

以上是切片:Go 的骨干!的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn