掌握Go语言:深入理解Go语言中的数组和切片,灵活处理数据的利器(16)

Go语言中的数组和切片是常用的集合类型,它们在处理数据时提供了不同的特性和灵活性。本文将深入探讨数组和切片的使用方法、特性、实例以及应用场景。

1. 数组和切片简介

在Go语言中,数组和切片都是集合类的类型,用于存储相同类型的元素。它们的主要区别在于数组的长度是固定的,而切片的长度是可变的。

1.1 数组

数组的长度在声明时就必须给定,并且在之后不会再改变。数组的长度是其类型的一部分,例如 [1]string[2]string 是两个不同的数组类型。

go 复制代码
// 示例1:声明一个长度为5的整型数组
arr := [5]int{1, 2, 3, 4, 5}

1.2 切片

切片是数组的一层简单封装,切片的长度可以随着元素数量的增长而增长,但不会随着元素数量的减少而减少。切片的类型字面量中只有元素的类型,没有长度。

go 复制代码
// 示例2:创建一个切片
slice := make([]int, 0, 5) // 初始长度为0,容量为5的整型切片

2. 切片表达式和容量

通过切片表达式,我们可以创建新的切片,指定切片的起始索引和结束索引。切片的容量表示底层数组中可以被切片窗口最右边元素的索引所覆盖的范围。

go 复制代码
// 示例3:使用切片表达式创建切片
arr := []int{1, 2, 3, 4, 5, 6, 7, 8}
slice := arr[3:6] // 从索引3到索引6(不包括)创建切片

3. 切片的容量增长规律

切片在容量不足时会进行扩容,一般情况下新容量是原容量的两倍,但当原长度大于或等于1024时,新容量基准为原容量的1.25倍,直至满足新长度。

go 复制代码
// 示例4:切片扩容规律演示
package main

import "fmt"

func main() {
    // 创建一个切片
    slice := make([]int, 0, 1)

    // 模拟切片扩容过程
    for i := 1; i <= 2048; i++ {
        slice = append(slice, i)
        fmt.Printf("Length: %d, Capacity: %d\n", len(slice), cap(slice))
    }
}

4. 切片的底层数组和追加元素

切片的底层数组永远不会被替换,扩容时会生成新的底层数组和新的切片。使用append函数对切片追加元素时,如果新长度不超过原容量,底层数组保持不变。

go 复制代码
// 示例5:使用append函数追加元素
slice := []int{1, 2, 3}
slice = append(slice, 4, 5) // 追加元素4和5到切片末尾

5. 应用场景

  • 数组 :适合用于表示固定长度的数据集合,如一周的天数 [7]string

    go 复制代码
    daysOfWeek := [7]string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}
  • 切片:常用于动态增长的数据集合,如日志收集、HTTP请求的处理等。

    go 复制代码
    logEntries := []string{"entry1", "entry2", "entry3"}
  • 切片扩容:当需要动态管理数据集合大小时,切片的自动扩容特性尤为重要,如读取文件内容、处理大量数据等场景。

    go 复制代码
    data := make([]byte, 0, 1024)
    // 读取文件内容并追加到切片
    for {
        chunk := readFromFile()
        if chunk == nil {
            break
        }
        data = append(data, chunk...)
    }

6. 进销存示例

go 复制代码
package main

import "fmt"

func main() {
    // 声明一个存储商品名称的数组
    var products [3]string

    // 添加商品名称到数组中
    products[0] = "手机"
    products[1] = "电脑"
    products[2] = "平板"

    // 声明一个切片用于存储每个商品的库存数量
    var inventory []int

    // 初始化库存数量
    inventory = append(inventory, 10) // 手机库存数量
    inventory = append(inventory, 20) // 电脑库存数量
    inventory = append(inventory, 15) // 平板库存数量

    // 显示每个商品的名称和库存数量
    for i, product := range products {
        fmt.Printf("商品名称: %s, 库存数量: %d\n", product, inventory[i])
    }
}

以上代码是一个简单的 Go 语言程序,用于模拟一个简单的进销存系统。让我们逐行解释这段代码:

  1. package main:声明了这个文件属于 main 包,这是 Go 语言程序的入口包。

  2. import "fmt":导入了 fmt 包,这个包实现了格式化输入输出的功能,我们可以使用它来打印输出信息到控制台。

  3. func main() { ... }:定义了程序的主函数,是程序执行的入口点。

  4. var products [3]string:声明了一个长度为 3 的字符串数组,用于存储商品名称。数组的长度是固定的,并且初始化为零值(空字符串)。

  5. products[0] = "手机"products[1] = "电脑"products[2] = "平板":将商品名称分别赋值给数组中的每个元素。

  6. var inventory []int:声明了一个整型切片,用于存储每个商品的库存数量。切片的长度可以动态增长,初始时长度为 0。

  7. inventory = append(inventory, 10)inventory = append(inventory, 20)inventory = append(inventory, 15):使用 append 函数向切片中追加元素,分别表示手机、电脑和平板的库存数量。

  8. for i, product := range products { ... }:使用 range 关键字遍历数组 productsi 表示当前索引,product 表示当前商品名称。在循环中,通过索引 i 可以从切片 inventory 中获取对应商品的库存数量,然后将商品名称和库存数量打印输出到控制台。

这段代码演示了如何使用数组和切片来实现一个简单的进销存系统,通过循环遍历打印出每个商品的名称和对应的库存数量。

7. 总结

  • 数组长度固定,切片长度可变。
  • 切片通过窗口查看底层数组,容量为切片窗口最右边元素的索引。
  • 切片扩容规律:一般为原容量的两倍,但长度大于等于1024时为1.25倍。
  • 切片的底层数组不会被替换,append返回新切片。
  • 数组适用于固定长度的集合,切片适用于动态管理数据集合。
相关推荐
用户6757049885022 分钟前
【AI开发实战】从想法到上线,我用AI全栈开发了一款记账微信小程序
后端·aigc·ai编程
Moment3 分钟前
作为前端,如果使用 Langgraph 实现第一个 Agent
前端·javascript·后端
神奇小汤圆4 分钟前
高并发接口总被打崩?我用 ArrayBlockingQueue + 底层源码深度剖析搞定流控
后端
木易 士心5 分钟前
MyBatis Plus 核心功能与用法
java·后端·mybatis
Victor3567 分钟前
MongoDB(93)如何使用变更流跟踪数据变化?
后端
用户6757049885027 分钟前
全网都在推 Claude Code,但只有这篇文章教你如何“真正”能用
后端·aigc·claude
Victor35610 分钟前
MongoDB(94)什么是MongoDB Atlas?
后端
苏三说技术21 分钟前
为什么越来越多的大厂抛弃MCP,转向CLI?
后端
Rust研习社30 分钟前
Rust 写时克隆智能指针 Cow
后端·rust·编程语言
董董灿是个攻城狮32 分钟前
库克不再担任苹果 CEO,附全员信
后端