
本文将深入探讨在 Go 语言中创建多维数组的两种主要方式:数组的数组和切片的切片。我们将详细比较这两种方法的内存使用、灵活性以及作为参数传递时的行为差异,并通过代码示例展示它们的特性和适用场景,帮助开发者选择最适合其需求的数据结构。
数组的数组 (Array of Arrays)
在 Go 中,我们可以使用数组的数组来创建多维数组。这种方式创建的多维数组在内存中是连续存储的,因此访问效率较高。
package mainimport "fmt"func main() { fmt.Println("Array of Arrays") a := [2][2]int{{0, 1}, {2, 3}} for i := 0; i < 2; i++ { for j := 0; j < 2; j++ { fmt.Printf("a[%d][%d] = %d at %pn", i, j, a[i][j], &a[i][j]) } }}
优点:
内存连续,访问效率高。内存占用相对较小,尤其是在维度和大小固定的情况下。
缺点:
Shakker
多功能AI图像生成和编辑平台
103 查看详情
大小固定,灵活性较差。在声明时必须指定所有维度的大小。作为函数参数传递时,会进行值拷贝,可能导致性能问题。
切片的切片 (Slice of Slices)
另一种创建多维数组的方式是使用切片的切片。切片是 Go 中一种动态数组,因此切片的切片可以创建大小可变的多维数组。
package mainimport "fmt"func main() { fmt.Println("Slice of Slices") b := [][]int{{0, 1}, {2, 3}} for i := 0; i < 2; i++ { for j := 0; j < 2; j++ { fmt.Printf("b[%d][%d] = %d at %pn", i, j, b[i][j], &b[i][j]) } }}
优点:
大小可变,灵活性高。可以动态调整每个维度的大小。作为函数参数传递时,传递的是切片的引用,避免了值拷贝,提高了性能。
缺点:
内存不连续,访问效率相对较低。每个子切片都可能在不同的内存地址上分配。内存占用相对较大,因为需要额外的空间存储切片的头部信息。
内存使用对比
以下代码展示了创建相同大小的数组的数组和切片的切片,并比较了它们的内存使用情况。
package mainimport "fmt"import "runtime"func printMemUsage() { var m runtime.MemStats runtime.ReadMemStats(&m) fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc)) fmt.Printf("tTotalAlloc = %v MiB", bToMb(m.TotalAlloc)) fmt.Printf("tSys = %v MiB", bToMb(m.Sys)) fmt.Printf("tNumGC = %vn", m.NumGC)}func bToMb(b uint64) uint64 { return b / 1024 / 1024}func main() { // Array of Arrays fmt.Println("Array of Arrays") printMemUsage() a := [100000][3]int{{1,2,3},{4,5,6}} printMemUsage() _ = a // Slice of Slices fmt.Println("Slice of Slices") printMemUsage() b := [][]int{{1,2,3},{4,5,6}} printMemUsage() for i := 0; i < 100000 -2; i++ { b = append(b, []int{1,2,3}) } printMemUsage() _ = b}
从输出结果可以看出,相同大小的数组的数组比切片的切片占用更少的内存。
函数参数传递
数组是值类型,当作为函数参数传递时,会进行值拷贝。这意味着在函数内部修改数组不会影响原始数组。切片是引用类型,当作为函数参数传递时,传递的是切片的引用。这意味着在函数内部修改切片会影响原始切片。
package mainimport "fmt"func f1(a [2][2]int) { fmt.Println("I'm a function modifying an array of arrays argument") a[0][0] = 100}func f2(b [][]int) { fmt.Println("I'm a function modifying an slice of slices argument") b[0][0] = 100}func main() { fmt.Println("Array of arrays") a := [2][2]int{{0, 1}, {2, 3}} fmt.Printf("Before %vn", a) f1(a) fmt.Printf("After %vnn", a) fmt.Println("Slice of slices") b := [][]int{{0, 1}, {2, 3}} fmt.Printf("Before %vn", b) f2(b) fmt.Printf("After %vn", b)}
总结
大小固定可变内存连续不连续内存占用较小较大灵活性较低较高参数传递值拷贝引用传递
选择建议:
如果多维数组的大小在编译时已知且不会改变,则应选择数组的数组,以获得更高的性能和更低的内存占用。如果多维数组的大小需要在运行时动态调整,或者需要更高的灵活性,则应选择切片的切片。
总而言之,理解数组的数组和切片的切片之间的差异,可以帮助开发者在 Go 语言中更有效地创建和使用多维数组,从而编写出更高效、更灵活的代码。
以上就是在 Go 中创建多维数组:数组的数组与切片的切片的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1136855.html
微信扫一扫
支付宝扫一扫