独家封印解开:Go语言列表List操作大揭秘

简介: 独家封印解开:Go语言列表List操作大揭秘

/ Go 语言列表 List 使用指南 /

Go 语言中并没有内置的列表 List 类型,但可以通过 slice、数组或链表实现列表功能。合理实现列表可以解决很多实际编码问题。

本文将全面介绍如何在 Go 语言中实现列表,内容涵盖

  1. 数组实现列表
  2. 切片实现列表
  3. 链表实现灵活列表
  4. 列表基本操作实现
  5. 线程安全列表
  6. 常见算法实现
  7. 列表与切片区别
  8. 应用场景


1

 

1. 数组实现列表

可以使用数组来实现简单的列表:

// 定义一个最大长度为100的int列表
var list [100]int
// 加入两个元素 
list[0] = 1  
list[1] = 2
// 读取第一个元素
v := list[0]
// 遍历数组列表
for i := 0; i < len(list); i++ {
  v := list[i]
  fmt.Println(v) 
}

数组实现的列表长度是固定的,删除元素后会留下空洞,无法动态缩容。

再来看一个例子:

// 定义一个最大长度为3的字符串列表
var strList [3]string 
// 尾部追加元素
strList[0] = "foo"
strList[1] = "bar"
// 头部插入元素
strList[2] = strList[1]
strList[1] = "baz"
// 读取第2个元素
v := strList[1]
// 遍历列表
for i := 0; i < len(strList); i++ {
  fmt.Println(strList[i]) 
}
// 删除第1个元素
strList[1] = ""

数组实现列表主要特点是简单直接,但是不够灵活。


2

 

2. 切片实现列表

切片实现的列表功能更加完整:

// 定义一个字符串切片
var strList []string
// 尾部追加元素  
strList = append(strList, "foo")
strList = append(strList, "bar")
// 读取第一个元素
v := strList[0] 
// 遍历切片列表
for i := range strList {
  fmt.Println(strList[i])
}
// 删除第1个元素
strList = append(strList[:1], strList[2:]...) 

切片列表可以动态增长,并且可以很方便地在尾部快速添加元素。

再来看一个例子:

// 定义一个数值切片
var numList []float64
// 尾部添加元素
numList = append(numList, 1.2)
// 头部添加元素 
numList = append([]float64{2.3}, numList...)
// 中间位置添加元素
numList = append(numList[:1], append([]float64{3.4}, numList[1:]...)...)
// 读取第2个元素
v := numList[1] 
// 删除第1个元素
numList = append(numList[:1], numList[2:]...)

切片允许很容易在头部或中间位置添加元素。


3

 

3. 链表实现灵活列表

可以通过自定义链表结构实现功能更加完备的列表:

// 链表节点
type Node struct {
  Value int
  Next *Node
}
// 初始化一个空链表 
var list List
// 尾部插入元素
node := &Node{Value: 1}
list.Append(node)
node = &Node{Value: 2}
list.Append(node)  
// 读取第1个节点
node := list.Head.Next 
// 遍历链表
for n := list.Head; n != nil; n = n.Next {
  fmt.Println(n.Value)
}
// 删除第2个节点
list.Remove(node.Next) 

链表需要自己实现相关的插入、删除、遍历逻辑,但是可以非常灵活地管理元素。

再举一个详细例子:

// 定义链表节点
type Node struct {
  Value int
  Next *Node
}
// 初始化链表
list := new(List)
// 头插法建立链表 
header := &Node{}
list.Append(header)
p := header
for i := 1; i <= 5; i++ {
  tmp := &Node{Value: i}
  p.Next = tmp
  p = tmp
}
// 尾插法插入元素 
tail := &Node{Value: 6}
p.Next = tail
// 删除第2个节点
list.Remove(header.Next.Next)
// 查找节点
n := list.Find(2)
// 反转链表
list.Reverse(header)
// 遍历链表
for n := header.Next; n != nil; n = n.Next {
  fmt.Println(n.Value)  
}

链表需要自己实现各种算法,但是可以非常灵活。


4

 

4. 列表基本操作实现

下面实现列表的一些基本操作:

尾部添加元素

对数组或切片使用 append 直接追加:

list = append(list, v)

对链表可以用尾插法:

node := &Node{Value: v}
tail.Next = node 
tail = node

头部添加元素

对切片可使用 append 向前追加:

list = append([]int{v}, list...)

对链表可用头插法:

node := &Node{Value: v}
node.Next = head.Next
head.Next = node

中间位置添加元素

对切片,需要创建新切片并复制元素:

list = append(list[:i], append([]int{v}, list[i:]...)...)

对链表直接修改指针完成插入:

node := &Node{Value:v}
node.Next = p.Next 
p.Next = node

读取元素

数组和切片直接索引定位:

v := list[i]

    删除元素

    数组切片创建新切片完成删除:

    list = append(list[:i], list[i+1:]...)

    链表修改指针完成删除:

    p.Next = p.Next.Next


    5

     

    5. 线程安全列表

    上述列表都不是线程安全的,可以使用同步原语实现线程安全:

    import "sync"
    // 定义一个互斥锁
    var mutex sync.Mutex
    // 加锁保护列表
    mutex.Lock() 
    list = append(list, v)
    mutex.Unlock()
    // 使用读写锁分别保护读写
    var rw sync.RWMutex
    rw.RLock()
    v = list[0]  
    rw.RUnlock()
    rw.Lock()
    list = append(list, v)  
    rw.Unlock()

    加锁可以实现线程安全,但是需要权衡锁带来的性能损耗。


    6

     

    6. 常见算法实现

    列表可以实现各种常见算法:

    排序

    切片列表可以使用 sort 包排序:

    sort.Ints(list)

    链表可以实现 sort 接口排序:

    sort.Sort(list)

    查找

    顺序查找:

    for i := 0; i < len(list); i++ {
      if list[i] == v {
        return i
      }
    }
    return -1 

    二分查找需要列表已排序:

    func binarySearch(list []int, v int) int {
      // 二分查找算法
      return index 
    }

    翻转

    数组可以复制反序写入:

    for i := 0; i < len(list); i++ {
      reversed[len(list)-i-1] = list[i] 
    }

    链表修改指针顺序:

    var prev *Node
    for cur := head.Next; cur != nil; {
      nxt := cur.Next
      cur.Next = prev
      prev = cur 
      cur = nxt
    }
    head.Next = prev

    7

     

    7. 列表与切片区别

    列表与切片的区别主要是:

    • 列表强调顺序性,切片可无序
    • 列表可以快速插入删除,切片更适合追加
    • 列表长度固定,切片动态大小


    8

     

    8. 应用场景

    列表常见使用场景包括:

    • 待办任务列表
    // 待办任务队列  
    var taskQueue []*Task 
    // 添加任务
    taskQueue = append(taskQueue, NewTask(params))
    // 获取执行任务  
    task := taskQueue[0] 
    taskQueue = taskQueue[1:]
    // 已完成任务列表
    var doneList []*Task

    商品列表

    // 商品列表
    var productList []*Product
    // 添加商品
    productList = append(productList, NewProduct(name, desc))
    // 删除下架商品
    for i := 0; i < len(productList); i++ {
      if !productList[i].OnSale {
        productList = append(productList[:i], productList[i+1:]...) 
      }
    }

    LRU 缓存淘汰

    // 双向链表
    type Node struct {
      Prev, Next *Node
      Key, Value interface{}
    }
    // Get时将节点移到表头  
    lru.Evict(node)
    lru.Add(node)
    // 淘汰链表尾节点
    tail := lru.tail 
    lru.Remove(tail)

    列表还可以用来实现栈、队列等数据结构。


    9

     

    总结

    本文全面介绍了 Go 语言实现高效列表的方法,包含数组、切片和链表实现,分析它们的特点,使用示例代码演示各种操作的实现,并对比了列表与切片的区别,以及举例列出了使用场景。希望可以帮助您深入理解 Go 语言中的列表实现和应用。如果有任何问题,非常欢迎您提出讨论。


    目录
    相关文章
    |
    2月前
    |
    运维 监控 算法
    监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
    在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
    |
    2月前
    |
    编译器 Go
    揭秘 Go 语言中空结构体的强大用法
    Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
    |
    1月前
    |
    人工智能 Java
    Java 中数组Array和列表List的转换
    本文介绍了数组与列表之间的相互转换方法,主要包括三部分:1)使用`Collections.addAll()`方法将数组转为列表,适用于引用类型,效率较高;2)通过`new ArrayList&lt;&gt;()`构造器结合`Arrays.asList()`实现类似功能;3)利用JDK8的`Stream`流式计算,支持基本数据类型数组的转换。此外,还详细讲解了列表转数组的方法,如借助`Stream`实现不同类型数组间的转换,并附带代码示例与执行结果,帮助读者深入理解两种数据结构的互转技巧。
    Java 中数组Array和列表List的转换
    |
    29天前
    |
    容器
    HarmonyOS NEXT - 列表布局(List)
    列表(List)是一种用于展示结构化、可滚动信息的复杂容器,适用于同类数据集合的呈现(如通讯录、音乐列表等)。通过垂直或水平排列子组件`ListItem`或`ListItemGroup`,可实现单个视图或多视图组合。支持条件渲染、循环渲染和懒加载等优化方式。 - **分隔线**:通过`divider`属性添加分隔线,并自定义粗细、颜色及边距。 - **滚动条**:使用`scrollBar`属性控制滚动条显示,支持按需显示(`BarState.Auto`)。 - **代码示例**:包含静态列表项、分组头布局、循环渲染及分隔线配置。
    83 0
    |
    2月前
    |
    开发框架 前端开发 Go
    eino — 基于go语言的大模型应用开发框架(二)
    本文介绍了如何使用Eino框架实现一个基本的LLM(大语言模型)应用。Eino中的`ChatModel`接口提供了与不同大模型服务(如OpenAI、Ollama等)交互的统一方式,支持生成完整响应、流式响应和绑定工具等功能。`Generate`方法用于生成完整的模型响应,`Stream`方法以流式方式返回结果,`BindTools`方法为模型绑定工具。此外,还介绍了通过`Option`模式配置模型参数及模板功能,支持基于前端和用户自定义的角色及Prompt。目前主要聚焦于`ChatModel`的`Generate`方法,后续将继续深入学习。
    465 7
    |
    2月前
    |
    存储 缓存 监控
    企业监控软件中 Go 语言哈希表算法的应用研究与分析
    在数字化时代,企业监控软件对企业的稳定运营至关重要。哈希表(散列表)作为高效的数据结构,广泛应用于企业监控中,如设备状态管理、数据分类和缓存机制。Go 语言中的 map 实现了哈希表,能快速处理海量监控数据,确保实时准确反映设备状态,提升系统性能,助力企业实现智能化管理。
    48 3
    |
    2月前
    |
    存储 缓存 安全
    Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
    `sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
    |
    2月前
    |
    SQL 安全 Java
    阿里双十一背后的Go语言实践:百万QPS网关的设计与实现
    解析阿里核心网关如何利用Go协程池、RingBuffer、零拷贝技术支撑亿级流量。 重点分享: ① 如何用gRPC拦截器实现熔断限流; ② Sync.Map在高并发读写中的取舍。
    105 0
    |
    2月前
    |
    存储 算法 安全
    基于 Go 语言的公司内网管理软件哈希表算法深度解析与研究
    在数字化办公中,公司内网管理软件通过哈希表算法保障信息安全与高效管理。哈希表基于键值对存储和查找,如用户登录验证、设备信息管理和文件权限控制等场景,Go语言实现的哈希表能快速验证用户信息,提升管理效率,确保网络稳定运行。
    43 0
    |
    JSON Go 数据格式
    从零学 Go:列表与字典
    前面的文章主要介绍了 Go 容器的数组和切片的基本概念以及使用。切片是 Go 中提供了一种灵活,功能强悍的内置类型("动态数组")。与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。本文将会介绍列表与字典在 Go 语言中相关的使用。
    318 0

    热门文章

    最新文章

    下一篇
    oss创建bucket