当前位置: 首页 > news >正文

Go学习笔记:复杂数据类型——数组、切片、Map、结构体与指针


📝本文首发于 栏轩·阁

欢迎访问阅读原文,获取更好的阅读体验。


一、数组(Array)— 定长

数组是固定长度的,一旦声明就不能改变长度。

// 声明:var 变量名 [长度]类型varnums[3]intnums[0]=10nums[1]=20nums[2]=30// 声明 + 初始化nums:=[3]int{10,20,30}// 让 Go 自己数长度nums:=[...]int{10,20,30}// 自动推断长度为 3// 数组长度是类型的一部分nums1:=[3]int{1,2,3}nums2:=[5]int{1,2,3,4,5}// nums1 = nums2 ← ❌ 编译错误!长度不同,类型不同

数组的局限:长度固定,不够灵活。实际开发中很少直接用数组,更常用的是切片。


二、切片(Slice)— 动态数组 ✅ 最常用

切片是 Go最常用的数据结构,类似于 Python 的 list 或 Java 的 ArrayList。

2.1 创建切片

// 方式1:字面量创建names:=[]string{"Go","Python","Rust"}// 方式2:make 创建nums:=make([]int,3)// [0, 0, 0],长度 = 3nums:=make([]int,3,5)// 长度 = 3,容量 = 5// 方式3:从数组切取arr:=[5]int{1,2,3,4,5}slice:=arr[1:4]// [2, 3, 4] 左闭右开

2.2 切片的增删改查

// 追加元素nums:=[]int{1,2,3}nums=append(nums,4)// [1, 2, 3, 4]nums=append(nums,5,6)// [1, 2, 3, 4, 5, 6]// 合并两个切片nums=append(nums,[]int{7,8}...)// ... 把切片展开// 获取长度和容量fmt.Println(len(nums))// 8,实际元素个数fmt.Println(cap(nums))// 底层数组容量(自动扩容)// 遍历fori,v:=rangenums{fmt.Printf("索引 %d = %d\n",i,v)}

2.3 长度 vs 容量

nums:=make([]int,3,5)// 长度 3,容量 5// nums = [0, 0, 0, _, _]// ↑ 长度 ↑ 容量(底层数组总大小)fmt.Println(len(nums))// 3fmt.Println(cap(nums))// 5nums=append(nums,1)// 还有容量,不会重新分配nums=append(nums,2)// [0, 0, 0, 1, 2]nums=append(nums,3)// 容量不够了 → 自动扩容为 2 倍

💡len表示能访问多少个元素,cap表示底层数组能放多少个。追加元素时,如果没超过 cap 就不会重新分配内存,效率更高。


三、Map — 键值对

类似于其他语言的字典 / HashMap。

// 创建 map// map[键类型]值类型scores:=make(map[string]int)scores["张三"]=90scores["李四"]=85// 创建 + 初始化scores:=map[string]int{"张三":90,"李四":85,"王五":92,}// 取值(安全方式:带 ok 判断是否存在)score,ok:=scores["赵六"]ifok{fmt.Println("分数:",score)}else{fmt.Println("此人不存在")}// 删除delete(scores,"李四")// 遍历(注意:map 遍历顺序不固定!)forname,score:=rangescores{fmt.Printf("%s: %d\n",name,score)}

⚠️ 遍历 Map 时顺序不固定,每次运行可能都不一样。如果需要固定顺序,先把 key 取出来排序再遍历。


四、结构体(struct)— 自定义类型

4.1 定义和使用

// 定义结构体typeUserstruct{NamestringAgeintEmailstring}// 使用u1:=User{"pc",25,"pc@example.com"}// 按字段顺序(不推荐)u2:=User{Name:"pc",Age:25,Email:"pc@example.com"}// 指定字段名(推荐 ✅)u3:=User{Name:"pc"}// 只赋值部分字段,其余为零值// 访问字段fmt.Println(u2.Name)// "pc"u2.Age=26// 修改字段

4.2 结构体方法

Go 没有 class,但可以给 struct 绑定方法:

typeUserstruct{NamestringAgeint}// 值接收者(不修改原始数据)func(u User)SayHello(){fmt.Printf("你好,我是 %s,今年 %d 岁\n",u.Name,u.Age)}// 指针接收者(可以修改原始数据)func(u*User)Birthday(){u.Age++}// 使用u:=User{Name:"pc",Age:25}u.SayHello()// 你好,我是 pc,今年 25 岁u.Birthday()// Age 变成 26u.SayHello()// 你好,我是 pc,今年 26 岁

💡什么时候用值接收者 vs 指针接收者?

  • 只读不修改 → 值接收者
  • 需要修改字段 → 指针接收者
  • 结构体很大 → 指针接收者(避免复制开销)

五、指针 — 简单理解

Go 的指针没有 C 的指针运算,比 C 安全得多。

// & 取地址 * 取值x:=10p:=&x// p 是一个指向 int 的指针fmt.Println(p)// 0xc0000...(内存地址)fmt.Println(*p)// 10(取指针指向的值)*p=20// 通过指针修改 xfmt.Println(x)// 20

为什么需要指针?

// 没有指针:值传递,原来的值不变funcdouble(xint){x=x*2}// 有指针:可以修改原来的值funcdouble(x*int){*x=*x*2}n:=5double(&n)fmt.Println(n)// 10

💡 新手阶段掌握&*就够了。在 Go 里,大部分时间用的是指针接收者(struct 方法)和切片(内部就是指针),不需要像 C 那样手动操作指针。


六、完整示例

typeStudentstruct{NamestringScorefloat64}func(s Student)Info()string{status:="不及格"ifs.Score>=60{status="及格"}returnfmt.Sprintf("%s: %.1f分 - %s",s.Name,s.Score,status)}funcmain(){// 用结构体 + 切片组织数据students:=[]Student{{"张三",85},{"李四",42},{"王五",93},}// 用 map 索引index:=make(map[string]float64)for_,s:=rangestudents{index[s.Name]=s.Score}// 查询for_,name:=range[]string{"张三","赵六"}{ifscore,ok:=index[name];ok{fmt.Printf("%s 的分数: %.1f\n",name,score)}else{fmt.Printf("%s 不存在\n",name)}}// 遍历for_,s:=rangestudents{fmt.Println(s.Info())}}

七、小结

类型特点常用程度
数组[n]T定长,用的少⭐⭐
切片[]T动态长度,最常用⭐⭐⭐⭐⭐
Mapmap[K]V键值对,快速查询⭐⭐⭐⭐
结构体struct组织多个字段,代替 class⭐⭐⭐⭐⭐
指针*T引用传值,注意 & 和 *⭐⭐⭐

下一课预告:错误处理与包管理——学会用好errorgo mod

http://www.cnnetsun.cn/news/4129979.html

相关文章:

  • 模糊C均值聚类(FCM)原理详解与Python实现:从概念到图像分割实战
  • TikTok Shop店群自动化管理系统:底层架构降维碾压,把店群做成工业流水线
  • SpringBoot企业员工转正晋升系统开发实战
  • 预警机时代的喜与忧:美军军事影像系统并非你想得那么好
  • 蓝桥杯国赛题解析:用扩展欧拉定理破解指数塔取模难题
  • 基于电流+功率2种MPC模型预测控制三相并网逆变器闭环仿真【电流预测+功率预测】(Simulink仿真、Matlab代码实现)
  • 针对国内医疗场景设计的医疗病床气撑解决方案有哪些核心竞争优势
  • 大厂 MCP 面试实录:设计需人工确认的高风险 Tool 与 RAG 知识库协作方案
  • 面向进度与可靠性的群体策略优化:提升Agentic强化学习在复杂任务中的表现
  • OpenClaw AI Agent框架实战:从安装部署到微信、PPT自动化应用
  • 技术面试变革:从算法到系统设计与工程实践
  • 企业站数据库设计实战:从范式到反范式,避坑指南与性能优化
  • Mac Mouse Fix使用指南:如何让一只99元的鼠标在macOS上逼近触控板体验
  • 当AI从“我的助手”变成“我们的同事”:WPS Comate给项目团队配了第四名队友
  • 移动端GUI智能体:数据环境协同缩放与视觉原生模型实践
  • WorkshopDL 完整上手攻略:游戏没买在 Steam,也能把创意工坊模组搬进本地
  • 星瞳Codex双模桌宠:TUI与Desktop模式的安装配置与实战指南
  • 二次元热血番剧一键生成:如何用知漫剧设计连贯的打斗分镜?
  • AI工具与云服务升级后配额不生效:从原理到排查的完整指南
  • JavaGuide开源项目:Java面试与AI模拟系统全解析
  • Java面试核心:HashMap、JVM与Spring技术精解
  • LangGraph实战:构建多智能体协作系统的核心原理与工程指南
  • Ceph与OpenStack超融合部署实战:从原理到生产级配置
  • Opencode实战:用AI快速生成网页原型,降低创意验证成本
  • 量化交易EA策略实测数据更新与监控系统构建指南
  • Java大厂面试实战:Spring Boot与Resilience4j深度解析
  • npm安全策略更新:详解2FA令牌权限变更与自动化流程适配
  • ComfyUI AI视频生成:从零搭建AnimateDiff工作流与避坑指南
  • Mac上部署多智能体系统:容器化隔离与会话持久化实战
  • 支撑大规模推理与 Agent 负载的企业 AI 基建如何选型?—— 基于 AWS 分层架构实现业务规模化稳定运行