前言:在编程的世界中,数据结构是组织和存储数据的关键方式,它直接影响着程序的性能和效率。Go 语言作为一门简洁高效的编程语言,在数据结构的使用上也有其独特的优势和特点。
目录
Go语言数据结构入门:数组、切片、映射、结构体、通道
一、数组:死板的储物柜
二、切片:哆啦a梦的百宝袋
三、映射:智能快递柜
三兄弟对比表
四、结构体:你的专属数据集装箱
五、通道(Channel):Goroutine的传声筒
通道类型详解
实战小项目:
游戏角色管理器
结构体+通道实战:多人在线游戏
总结
想象你有一个储物柜,格子数量固定,放满就不能加了:
// 记得先声明一下数组哦,一个能存放3本书的数组
var bookshelf [3]string
// 给柜子里的格子装上书
bookshelf[0] = "Go语言入门"
bookshelf[1] = "数据结构"
bookshelf[2] = "数据库原理"
// 我还想添加第四本书:bookshlef[3] = "西游记"
// 会报错哦,因为柜子装不了了就出现了越界错误
数组的特点:
newShelf := bookshelf // newShelf把我们的书柜搬走了,盗取我们的书
newShelf[0] = "盗版书,不要看" // 它是盗版的,不要看~
fmt.Println(bookshelf[0]) // 输出我们的第一本书名"Go语言入门"。
// 数组适合存放固定数量的东西,比如一周有七天。
切片就像哆啦A梦的口袋,想装多少装多少:
// 创建哆啦A梦的百宝袋(空尼基哇的)
var magicBag []string
// 现在来给百宝袋塞道具
magicBag = append(magicBag,"竹蜻蜓")
magicBag = append(magicBag,"任意门","时光机")
fmt.Println(magicBag) // 现在有了[竹蜻蜓 任意门 时光机]
切片核心技能:
自动扩容:袋子不够大时自动换大袋子
灵活裁剪:想要哪段切哪段
tools := magicBag[0:2] // 拿到前两个工具
fmt.Println(tools) // [竹蜻蜓 任意门]
fmt.Printf("长度:%d 容量:%d",
len(magicBag), // 当前元素数 → 3
cap(magicBag)) // 总容量 → 可能为4
// 用户列表、商品展示等动态数据都用切片!
映射(map)就像小区快递柜,凭取件码秒找包裹:
// 初始化快递柜
expressBox := map[string]string{
"SF1001": "王先生的显卡",
"JD2002": "李小姐的化妆品",
}
// 存新快递
expressBox["YT3003"] = "张同学的考研资料"
// 取快递(带检查)
package, exists := expressBox["JD2002"]
if exists {
fmt.Println("找到包裹:", package) // 李小姐的化妆品
} else {
fmt.Println("取件码无效")
}
// 删除包裹
delete(expressBox, "SF1001")
映射的魔法:
键值配对:一个钥匙开一个柜门
闪电查找:比翻列表快N倍
无序存储:快递柜不按顺序放
特性 | 数组 | 切片 | 映射 |
---|---|---|---|
长度 | 固定 | 可变 | 可变 |
查找方式 | 下标 | 下标 | 键(key) |
内存复制 | 整个复制 | 只复制指针 | 只复制指针 |
使用频率 | 较低 | 高 | 较高 |
典型场景 | 固定集合 | 动态列表 | 字典/配置 |
结构体就像乐高积木,让你自由组合不同类型的数据,打造专属数据结构:
// 定义玩家结构体(你的游戏角色蓝图)
type Player struct {
Name string // 字符串类型名字
Level int // 整数类型等级
Skills []string// 字符串切片技能
Equip struct { // 嵌套结构体装备
Weapon string
Armor string
}
}
// 创建玩家实例(组装乐高)
p := Player{
Name: "暗夜刺客",
Level: 99,
Skills: []string{"潜行", "背刺", "毒刃"},
Equip: struct {
Weapon string
Armor string
}{
Weapon: "幽冥匕首",
Armor: "影舞者斗篷",
},
}
// 访问结构体字段(操作你的角色)
fmt.Println(p.Name + "手持" + p.Equip.Weapon)
// 输出:暗夜刺客手持幽冥匕首
// 修改装备(升级武器!)
p.Equip.Weapon = "灭世双刃"
结构体超能力解析:
字段自由组合:混合int、string、slice等任意类型
嵌套结构:装备里再套装备(套娃警告)
通道是Go并发的灵魂,让协程(Goroutine)安全传递数据:
// 主函数:指挥中心
func main() {
// 创建无缓冲通道(同步对讲机)
msgChan := make(chan string)
// 启动协程:前线侦察兵
go scout(msgChan, "A区")
// 接收侦察兵报告(阻塞等待)
report := <-msgChan
fmt.Println("收到报告:", report) // 输出:A区安全!
}
// 侦察兵函数
func scout(ch chan string, area string) {
time.Sleep(time.Second) // 模拟侦察耗时
ch <- area + "安全!" // 发送报告
}
类型 | 创建方式 | 特点 | 适用场景 |
---|---|---|---|
无缓冲通道 | make(chan T) |
发送后必须立即接收 | 强同步任务(如信号通知) |
有缓冲通道 | make(chan T, 容量) |
可存储多个值(队列) | 生产消费模型 |
// 有缓冲通道示例(快递仓库)
packageChan := make(chan string, 3) // 容量3的仓库
// 生产者协程:入库
go func() {
packageChan <- "包裹1"
packageChan <- "包裹2"
packageChan <- "包裹3"
}()
// 消费者:出库
fmt.Println(<-packageChan) // 包裹1
fmt.Println(<-packageChan) // 包裹2
通道高级操作:
// 1. 关闭通道(贴上封条)
close(packageChan)
// 2. 循环接收直到通道关闭
for pkg := range packageChan {
fmt.Println("处理:", pkg)
}
// 3. 多路选择(监听多个通道)
select {
case msg := <-msgChan:
fmt.Println(msg)
case <-time.After(time.Second): // 超时控制
fmt.Println("响应超时!")
}
package main
import "fmt"
type Character struct {
Name string
Level int
Weapon string
}
func main() {
// 1. 创建角色切片
players := []Character{
{"刀客", 15, "青龙刀"},
{"法师", 23, "火焰杖"},
}
// 2. 添加新角色
newPlayer := Character{Name: "射手", Level: 10, Weapon: "穿云箭"}
players = append(players, newPlayer)
// 3. 创建角色ID映射
playerMap := make(map[int]Character)
for id, player := range players {
playerMap[id] = player
}
// 4. 按ID查找角色
searchID := 1
if char, exists := playerMap[searchID]; exists {
fmt.Printf("找到角色%d: %s (Lv.%d 武器:%s)\n",
searchID, char.Name, char.Level, char.Weapon)
}
}
package main
import (
"fmt"
"strconv"
"time"
)
type GameEvent struct {
PlayerID int
Action string
Target string
}
func main() {
// 游戏事件通道(100个事件缓冲)
eventChan := make(chan GameEvent, 100)
// 启动玩家协程
go playerHandler(1, "攻击BOSS", eventChan)
go playerHandler(2, "采集草药", eventChan)
// 事件处理器
for i := 0; i < 2; i++ {
event := <-eventChan
fmt.Printf("玩家%d: %s→%s\n",
event.PlayerID, event.Action, event.Target)
}
}
func playerHandler(id int, action string, ch chan GameEvent) {
time.Sleep(time.Duration(id) * time.Second)
ch <- GameEvent{
PlayerID: id,
Action: action,
Target: "地图" + strconv.Itoa(id),
}
}
程序执行结果:
玩家1: 攻击BOSS→地图1
玩家2: 采集草药→地图2
数组、切片和映射是 Go 语言常用数据结构。数组固定长度,适合存储预定规模数据;切片灵活可变,适配不确定长度集合;映射通过键值对高效查找。结构体能构建复杂类型,通道助力协程通信。在游戏开发中,切片动态管理角色,映射快速定位信息。掌握这些结构特点,利于开发高效代码。