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的net/http包

    快速上手GO的net/http包

    本文主要介绍了快速上手GO的net/http包,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-05-05
  • Golang中Gin框架中如何定义路由详解

    Golang中Gin框架中如何定义路由详解

    Gin是一个用Go语言编写的Web框架,具有高性能和易于使用的特点,本文将结合实际案例,详细介绍Gin框架的路由用法,有需要的小伙伴可以参考下
    2024-10-10
  • GO项目实战之Gorm格式化时间字段实现

    GO项目实战之Gorm格式化时间字段实现

    GORM自带的time.Time类型JSON默认输出RFC3339Nano格式的,下面这篇文章主要给大家介绍了关于GO项目实战之Gorm格式化时间字段实现的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • 详解go语言中并发安全和锁问题

    详解go语言中并发安全和锁问题

    这篇文章主要介绍了go语言中并发安全和锁问题,包含互斥锁解锁过程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-10-10
  • go-spew调试利器详解

    go-spew调试利器详解

    这篇文章主要介绍了调试利器 go-spew,go-spew 可以以一种非常友好的方式输出完整的数据结构信息,go-spew 支持一些自定义配置,可以通过 spew.Config 修改,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • golang类型断言的实现示例

    golang类型断言的实现示例

    在Go语言中,类型断言用于从接口类型获取其具体类型的值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-10-10
  • golang log4go的日志输出优化详解

    golang log4go的日志输出优化详解

    log4go源于google的一项log工程,但官方已经停止维护更新,下面这篇文章主要给大家介绍了关于golang log4go的日志输出优化的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-12-12
  • GoLang内存泄漏原因排查详解

    GoLang内存泄漏原因排查详解

    内存溢出是指程序在申请内存时,没有足够的内存空间供其使用,简单点说就是你要求分配的内存超出了系统能给你的,系统不能满足需求,于是产生溢出出现out of memory异常
    2022-12-12
  • go map搬迁的实现

    go map搬迁的实现

    本文主要介绍了go map搬迁的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • 使用go语言解析xml的实现方法(必看篇)

    使用go语言解析xml的实现方法(必看篇)

    下面小编就为大家带来一篇使用go语言解析xml的实现方法(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06

最新评论