Golang中切片长度和容量的区别示例详解

 更新时间:2024年01月24日 10:53:58   作者:Nex1395  
切片长度与容量在Go中很常见,切片长度是切片中可用元素的数量,而切片容量是从切片中第一个元素开始计算的底层数组中的元素数量,这篇文章主要给大家介绍了关于Golang中切片长度和容量区别的相关资料,需要的朋友可以参考下

首先要知道在Golang中,切片的底层实际就是数组。

1.切片的长度:

切片的长度指切片中元素的数量,可以使用len()函数查询其切片的长度。

示例1:

package main

import "fmt"

func main(){
    slice := []int{1,3,2,6,4}
    # 调用len查看长度
    length := len(slice)
    fmt.Printf("slice01的长度是:%v", length)
}

// 输出结果
// slice的长度是:5

在上面代码中,变量length就是切片的长度(结果是5)

2.切片的容量:

切片的容量是指切片底层数组的长度,可以使用cap()函数查看容量

示例2:

package main

import "fmt"

func main(){
    slice := []int{1,3,2,6,4}
    // 调用cap查看容量
    capacity := cap(slice)
    fmt.Printf("slice01的容量是:%v", capacity)
}

// 输出结果
// slice的容量是:5

在上面代码中,变量capacity就是切片的容量(结果也是5)

3.通过上面两个示例看不出区别,我们看下面的示例:

示例3

package main

import "fmt"

func main(){
    // 通过make函数来创建slice, 4表示切片的长度, 10标识切片的容量
    slice := make([]int, 4, 6)
    length := len(slice)
    capacity := cap(slice)
    fmt.Printf("slice01的长度是:%v\n", length)
    fmt.Printf("slice01的容量是:%v\n", capacity)
}

// 输出结果
// slice01的长度是:4
// slice01的容量是:6

你可以想象成:当执行slice := make([]int, 4, 10)的时候,程序在底层创建了一个长度为6的数组,切片slice引用了前面4个元素,就生成了slice这个切片,当前切片值是:{0, 0, 0, 0},剩下的2个元素则暂时没有引用。

4.通过对切片的增加,查看切片与底层数组的变化

我们知道,golang中切片和数组的主要区别在于数组是定长的,切片是变长的。但我们在示例3中定义了切片的容量是6,那如果超过6个元素了,将会发生什么呢?

示例4

package main

import "fmt"

func main(){
    // 通过make函数来创建slice, 4表示切片的长度, 10标识切片的容量
    slice := make([]int, 4, 6)
    length := len(slice)
    capacity := cap(slice)
    fmt.Printf("slice01的长度是:%v\n", length)
    fmt.Printf("slice01的容量是:%v\n", capacity)
    
    //第一次向切片slice内添加元素
    slice = append(slice, 1)
    //打印slice的长度,容量,内存地址(slice[0]的内存地址)
    fmt.Printf("\n\n第一次结果:")
    fmt.Printf("slice的长度是:%v\n", len(slice))
    fmt.Printf("slice的容量是:%v\n", cap(slice))
    fmt.Printf("slice的内存地址是:%v\n", &slice[0])
    
    // 第二次向slice内添加元素
    slice = append(slice, 1)
    //打印slice的长度,容量,内存地址(slice[0]的内存地址)
    fmt.Printf("\n\n第二次结果:")
    fmt.Printf("slice的长度是:%v\n", len(slice))
    fmt.Printf("slice的容量是:%v\n", cap(slice))
    fmt.Printf("slice的内存地址是:%v\n", &slice[0])
    
    // 第三次向slice内添加元素
    slice = append(slice, 1)
    //打印slice的长度,容量,内存地址(slice[0]的内存地址)
    fmt.Printf("\n\n第三次结果:")
    fmt.Printf("slice的长度是:%v\n", len(slice))
    fmt.Printf("slice的容量是:%v\n", cap(slice))
    fmt.Printf("slice的内存地址是:%v\n", &slice[0])
}

// slice01的长度是:4
// slice01的容量是:6


// 第一次结果:slice的长度是:5
// slice的容量是:6
// slice的内存地址是:0xc00000e390


// 第二次结果:slice的长度是:6
// slice的容量是:6
// slice的内存地址是:0xc00000e390


// 第三次结果:slice的长度是:7
// slice的容量是:12
// slice的内存地址是:0xc000060060

通过示例4我们可以发现:我们初始化切片长度为4, 容量为6的时候。

当第一次和第二次向切片内添加元素后,只有切片的长度增加,容量和内存地址都没改变

当第三次向切片内添加元素后,长度增加了1,容量变成了之前的2倍,内存地址也发生了改变。

由此我们可以推断出:

**总结:**当切片的元素长度超过了默认的容量之后,程序会重新创建一个底层数组和切片绑定,且新的数组的长度为原来的两倍(切片的容量变成原来的两倍)

5. 注意用法:

示例5

package main

import "fmt"

func main() {
	slice := make([]int, 4, 4)
	slice2 := make([]int, 4, 5)
    // 调用下方定义的test函数
	test(slice)
	test(slice2)

	// 输出两个切片调用test函数后的结果
	fmt.Printf("slice的结果: %v\n", slice)
	fmt.Printf("slice2的结果: %v\n", slice2)

}

func test(s []int) {
	s = append(s, 1)
	for i := 0; i < len(s); i++ {
		s[i] = 100
	}
}

// slice的结果: [0 0 0 0]
// slice2的结果: [100 100 100 100]

切片容量不同,导致了最终结果不同。

总结

到此这篇关于Golang中切片长度和容量区别的文章就介绍到这了,更多相关Golang切片长度和容量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go项目在GoLand中导入依赖标红问题的解决方案

    Go项目在GoLand中导入依赖标红问题的解决方案

    这篇文章主要介绍了Go项目在GoLand中导入依赖标红问题的解决方案,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-06-06
  • Golang对struct字段重新排序优化数据结构性能实践

    Golang对struct字段重新排序优化数据结构性能实践

    这篇文章主要为大家介绍了Golang对struct字段重新排序优化数据结构性能实践,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • golang cache带索引超时缓存库实战示例

    golang cache带索引超时缓存库实战示例

    这篇文章主要为大家介绍了golang cache带索引超时缓存库实战示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • 深入了解Go语言中context的用法

    深入了解Go语言中context的用法

    这篇文章主要为大家详细介绍了Go语言中context用法的相关知识,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-07-07
  • Go语言异常处理error、panic、recover的使用

    Go语言异常处理error、panic、recover的使用

    GO语言中引入的异常的处理方式为error、panic、recover ,本文主要介绍了Go语言异常处理error、panic、recover的使用,感兴趣的可以了解一下
    2024-08-08
  • Go语言中你不知道的Interface详解

    Go语言中你不知道的Interface详解

    对于go语言来说,设计最精妙的应该是interface了,直白点说interface是一组method的组合。下面这篇文章主要给大家介绍了关于Go语言中你不知道的Interface的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2018-02-02
  • PHP与Go语言之间的通信详解

    PHP与Go语言之间的通信详解

    相信大家都知道不同语言之间的通信方式有很多种,这篇文章详细的介绍了PHP与Go语言之间如何通信,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-10-10
  • Go语言实现定时器的原理及使用详解

    Go语言实现定时器的原理及使用详解

    这篇文章主要为大家详细介绍了Go语言实现定时器的两种方法:一次性定时器(Timer)和周期性定时器(Ticker),感兴趣的小伙伴可以跟随小编一起学习一下
    2022-12-12
  • 解读golang中的const常量和iota

    解读golang中的const常量和iota

    这篇文章主要介绍了golang中的const常量和iota,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • GoLang日志监控系统实现

    GoLang日志监控系统实现

    这篇文章主要介绍了GoLang日志监控系统的实现流程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12

最新评论