第四篇:《函数、指针与结构体:组织代码的核心工具》
变量是代码的“名词”函数是代码的“动词”。在 Go 语言中函数是第一公民支持多返回值、命名返回值和闭包。指针提供了对内存的间接访问能力但 Go 的指针比 C 更安全——不支持指针算术。结构体struct是 Go 组织数据的核心方式结合方法method可以实现面向对象编程中的“类”概念。本文系统讲解函数、指针与结构体的核心语法与最佳实践并通过一个“学生管理系统”的实战案例帮你掌握组织 Go 代码的核心工具。一、函数Go 代码的组织单元1.1 函数的基本声明Go 函数的声明格式为func 函数名(参数列表) 返回值列表 { 函数体 }// 无参数无返回值funcsayHello(){fmt.Println(Hello!)}// 带参数funcgreet(namestring){fmt.Printf(Hello, %s!\n,name)}// 带返回值funcadd(aint,bint)int{returnab}// 参数类型相同时可以省略前一个的类型声明funcmultiply(a,bint)int{returna*b}1.2 多返回值Go 的特色Go 是少数支持多返回值的语言之一这是 Go 错误处理机制的基础// 返回两个值商和余数funcdivide(a,bint)(int,int){quotient:a/b remainder:a%breturnquotient,remainder}funcmain(){q,r:divide(10,3)fmt.Printf(商: %d, 余数: %d\n,q,r)// 商: 3, 余数: 1// 如果不需要某个返回值使用空白标识符 _q2,_:divide(20,6)fmt.Println(商:,q2)}1.3 命名返回值Go 允许为返回值命名这在函数体中可以像普通变量一样使用return 语句可以不带参数自动返回// 命名返回值funcdivideWithName(a,bint)(quotientint,remainderint){quotienta/b remaindera%breturn// 裸返回返回 quotient 和 remainder}// 在文档中更清晰funcgetUserInfo(idint)(namestring,ageint,emailstring){// 实际开发中这里会从数据库查询nameAliceage30emailaliceexample.comreturn} 使用建议对于短函数1-3 行命名返回值可能增加代码冗余对于长函数或返回多个相同类型值时命名返回值能提高可读性。1.4 可变参数使用 …T 语法接收任意数量的参数// 求和支持任意数量的参数funcsum(nums...int)int{total:0for_,num:rangenums{totalnum}returntotal}funcmain(){fmt.Println(sum(1,2,3))// 6fmt.Println(sum(1,2,3,4,5))// 15// 传入切片时使用 ... 展开nums:[]int{1,2,3,4}fmt.Println(sum(nums...))// 10}1.5 匿名函数与闭包Go 支持在函数内部定义匿名函数并可以捕获外部变量闭包// 匿名函数直接调用funcmain(){func(msgstring){fmt.Println(msg)}(Hello from anonymous!)}// 闭包函数捕获外部变量funccounter()func()int{count:0returnfunc()int{countreturncount}}funcmain(){c:counter()fmt.Println(c())// 1fmt.Println(c())// 2fmt.Println(c())// 3}二、指针内存的“门牌号”Go 的指针提供了对变量内存地址的访问能力但比 C 更安全——不支持指针算术运算如 p。2.1 指针的基本操作funcmain(){x:42p:x// p 是指向 x 的指针类型为 *intfmt.Println(p)// 内存地址如 0xc00000a0a8fmt.Println(*p)// 解引用输出 42*p100// 通过指针修改 x 的值fmt.Println(x)// 输出 100}2.2 值传递 vs 指针传递Go 中所有参数都是值传递传递副本但对于大型数据结构使用指针传递可以避免拷贝开销并能修改原值// 值传递函数内修改不影响外部funcupdateValue(vint){v100}// 指针传递函数内修改影响外部funcupdatePointer(p*int){*p100}funcmain(){a:10updateValue(a)fmt.Println(a)// 10未改变updatePointer(a)fmt.Println(a)// 100已改变}2.3 指针接收者 vs 值接收者与结构体方法相关在 Go 中方法可以定义在结构体上接收者可以是值或指针typePersonstruct{NamestringAgeint}// 值接收者不能修改原值func(p Person)SayHello(){fmt.Printf(你好我是 %s今年 %d 岁\n,p.Name,p.Age)}// 指针接收者可以修改原值func(p*Person)SetAge(ageint){p.Ageage}funcmain(){p:Person{Name:Alice,Age:30}p.SetAge(31)// 可以修改原值p.SayHello()// 你好我是 Alice今年 31 岁}选择原则需要修改结构体字段 → 使用指针接收者结构体较大 64 字节 → 使用指针接收者避免拷贝开销结构体较小且不需要修改 → 可以使用值接收者三、结构体Struct组合数据的载体Go 没有类的概念但通过结构体和方法可以实现面向对象编程的核心能力。3.1 定义与初始化// 定义结构体typeStudentstruct{IDintNamestringAgeintScores[]int}// 多种初始化方式funcmain(){// 方式1按字段顺序不推荐可读性差s1:Student{1,Alice,20,[]int{90,85,92}}// 方式2使用字段名推荐s2:Student{ID:2,Name:Bob,Age:21,}// 方式3先声明再赋值零值初始化vars3 Student s3.ID3s3.NameCharlie// 方式4使用 new 关键字返回指针s4:new(Student)// *Student 类型s4.ID4s4.NameDavid}3.2 匿名结构体适用于一次性使用的场景funcmain(){// 匿名结构体直接初始化config:struct{HoststringPortint}{Host:localhost,Port:8080,}fmt.Printf(%v\n,config)// {Host:localhost Port:8080}}3.3 结构体嵌套Go 支持结构体嵌套可以实现类似继承的效果typeAddressstruct{CitystringCountrystring}typeEmployeestruct{NamestringAgeintAddress Address// 嵌套结构体}funcmain(){e:Employee{Name:Alice,Age:30,Address:Address{City:Beijing,Country:China,},}// 访问嵌套字段fmt.Println(e.Address.City)// Beijing}3.4 匿名字段嵌入式结构体Go 支持“嵌入”结构体被嵌入的字段可以直接访问typeEmployeestruct{NamestringAgeintAddress// 匿名字段嵌入式}funcmain(){e:Employee{Name:Alice,Age:30,Address:Address{City:Beijing,Country:China,},}// 可以直接访问嵌入的字段fmt.Println(e.City)// Beijing不需要 e.Address.Cityfmt.Println(e.Country)// China}四、实战学生管理系统综合运用结构体、方法和函数实现一个简单的学生管理系统packagemainimportfmt// 学生结构体typeStudentstruct{IDintNamestringScores[]float64}// 计算平均分func(s Student)Average()float64{iflen(s.Scores)0{return0}total:0.0for_,score:ranges.Scores{totalscore}returntotal/float64(len(s.Scores))}// 判断是否及格平均分 60func(s Student)IsPassed()bool{returns.Average()60}// 学生管理系统typeStudentManagerstruct{Studentsmap[int]Student}// 添加学生func(sm*StudentManager)AddStudent(s Student){ifsm.Studentsnil{sm.Studentsmake(map[int]Student)}sm.Students[s.ID]s}// 根据 ID 查找学生func(sm*StudentManager)FindByID(idint)(Student,bool){s,ok:sm.Students[id]returns,ok}// 列出所有学生信息func(sm*StudentManager)ListAll(){iflen(sm.Students)0{fmt.Println(暂无学生数据)return}fmt.Println( 学生列表 )for_,s:rangesm.Students{fmt.Printf(ID: %d, 姓名: %s, 平均分: %.2f, 状态: %s\n,s.ID,s.Name,s.Average(),map[bool]string{true:及格,false:不及格}[s.IsPassed()])}}funcmain(){sm:StudentManager{}// 添加学生sm.AddStudent(Student{ID:1,Name:Alice,Scores:[]float64{90,85,92}})sm.AddStudent(Student{ID:2,Name:Bob,Scores:[]float64{50,60,55}})sm.AddStudent(Student{ID:3,Name:Charlie,Scores:[]float64{70,75,80}})// 查找学生ifs,ok:sm.FindByID(2);ok{fmt.Printf(找到学生: %s, 平均分: %.2f\n,s.Name,s.Average())}// 列出所有sm.ListAll()}五、小结函数支持多返回值、命名返回值、可变参数和闭包是 Go 代码的基本组织单元。指针使用 取地址* 解引用不支持指针算术。指针传递允许修改原值避免拷贝开销。结构体组合数据的核心方式支持嵌套和匿名字段。方法可以定义在值接收者或指针接收者上。选择原则需要修改字段时用指针接收者不需要修改且结构体较小时用值接收者。

相关新闻

【超详细】二分查找(折半查找)核心知识点全解析(含多场景代码实现)

【超详细】二分查找(折半查找)核心知识点全解析(含多场景代码实现)

一、前言二分查找(Binary Search)是算法领域最经典、最高效的查找算法之一,其时间复杂度为 O(logn),相比顺序查找的 O(n) 效率提升呈指数级。它是「分治思想」的典型应用,也是面试中高频考察的算法考点。本文将从核心概…

2026/9/26 3:56:31 阅读更多 →
针对络合态重金属废水,探索集成Tulsimer 树脂的深度处理与资源回收工艺

针对络合态重金属废水,探索集成Tulsimer 树脂的深度处理与资源回收工艺

在日益严格的环保政策与循环经济需求的双重驱动下,许多工业企业正面临重金属废水治理的深层挑战:络合态重金属难以稳定达标、危废处置成本高昂、以及有价值金属资源的流失。传统沉淀、氧化等工艺在处理此类废水时,往往遇到瓶颈。本文将探讨一…

2026/9/26 22:24:35 阅读更多 →
Tiva™ TM4C129XNCZAD寄存器编程实战:从模块化理解到高效驱动开发

Tiva™ TM4C129XNCZAD寄存器编程实战:从模块化理解到高效驱动开发

1. 从寄存器列表到高效编程:Tiva™ TM4C129XNCZAD 实战指南看到这份长长的寄存器列表,很多刚接触 Tiva™ TM4C129XNCZAD 或者从 Arduino 这类高级框架转过来的朋友可能会有点懵。手册里几百个寄存器,每个都有一堆位域,难道写个点灯…

2026/10/2 2:53:48 阅读更多 →

最新新闻

数字多波束形成(DBF)的MATLAB仿真:从阵列流型到波束图

数字多波束形成(DBF)的MATLAB仿真:从阵列流型到波束图

简介:数字多波束形成(DBF)是阵列信号处理中的核心环节,常用于雷达、通信与声呐系统。这份MATLAB仿真代码包面向需要理解多波束方向图合成原理的初学者,通过可配置参数直观展示波束指向与阵列响应的关系。资源共2个文件…

2026/10/3 10:17:04 阅读更多 →
30B大模型手机部署实战:UFS 4.1存储优化与量化方案

30B大模型手机部署实战:UFS 4.1存储优化与量化方案

1. 当30B大模型撞上手机存储:一场注定要打的硬仗把30B参数的大模型塞进手机,这件事在两年前听起来像是天方夜谭。但到了今天,端侧AI已经从“能不能跑”进入到了“怎么跑得动、跑得稳”的阶段。我最近在折腾本地大模型部署的时候,反…

2026/10/3 10:17:04 阅读更多 →
Codex与Claude协同开发:额度优化与账号安全策略

Codex与Claude协同开发:额度优化与账号安全策略

1. 两套工具同时开工,我到底在图什么先把结论摆在前面:我同时用 Codex 和 Claude 做日常开发,不是因为钱多烧得慌,也不是因为对某个工具有信仰。核心原因只有一个——它们的能力边界不一样,而我的任务类型也不一样。把…

2026/10/3 10:17:04 阅读更多 →
Codex与Claude组合使用指南:额度优化与封号风险规避

Codex与Claude组合使用指南:额度优化与封号风险规避

1. 为什么要把 Codex 和 Claude 放在一起用 先说结论:我同时用 Codex 和 Claude 做 AI 编程,不是因为钱多烧得慌,也不是因为喜欢折腾,而是因为这两个工具在真实项目里的能力边界完全不同。单用任何一个,都会在某个环节…

2026/10/3 10:17:04 阅读更多 →
Qt多媒体开发全流程实战:播放、采集、多线程与打包

Qt多媒体开发全流程实战:播放、采集、多线程与打包

做Qt多媒体开发也有几年了,这个模块算是我用得最多、也最容易被新手误会的部分。很多人以为Qt搞多媒体就是拖个控件、调用几个API,实际上真到做播放器、接摄像头、处理采集推流的时候,坑比想象中多得多。这篇文章我按自己实际项目的踩坑路径&…

2026/10/3 10:17:03 阅读更多 →
云端Agent部署实战:AI模组与阵列式服务器配置指南

云端Agent部署实战:AI模组与阵列式服务器配置指南

1. 从"算力焦虑"说起:为什么CPU突然又被推到了台前 过去两年,只要聊到AI,话题几乎绕不开GPU。显存多大、卡多贵、排队多久,成了圈子里默认的寒暄方式。但真正在一线做推理服务部署的人心里都清楚一件事: GP…

2026/10/3 10:16:03 阅读更多 →

日新闻

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南

把回忆蒸馏成 AI 的浪漫实验:为什么你需要前任.skill 完整指南 【免费下载链接】ex-skill 前任 skill 项目地址: https://gitcode.com/gh_mirrors/exsk/ex-skill 前任.skill 是一个运行在 Claude Code 上的开源 Skill:导入微信、iMessage、短信、…

2026/10/3 0:00:27 阅读更多 →
45个经典Linux面试题:从命令到网络排障的完整考点解析

45个经典Linux面试题:从命令到网络排障的完整考点解析

刚开始带应届生的时候,我最头疼的就是他们拿着一摞Linux面试题背得滚瓜烂熟,一上机全露馅。后来自己从被面的人变成面别人的人,才慢慢摸清楚:Linux面试题考的根本不是答案本身,而是你面对一个不确定的系统问题时&#…

2026/10/3 0:01:28 阅读更多 →
SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

SAP生产预留实战指南:MB21/MB23/MB25协同与MRP集成

简介:本资源是一份面向SAP ABAP开发人员、生产计划专员及ERP实施顾问的实操型操作指南,聚焦SAP生产预留核心业务场景,系统解决物料预留创建、查询、校验与批量处理等高频问题。文档以结构化方式覆盖预留背景原理、OMC2编码规则、工厂级参数配…

2026/10/3 0:01:28 阅读更多 →

周新闻

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/10/3 9:14:33 阅读更多 →
SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/10/3 9:47:50 阅读更多 →
FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏

FireRed-OpenStoryline少样本仿写深度解析:AI Agent如何复刻你的独特文案风格与节奏 【免费下载链接】FireRed-OpenStoryline FireRed-OpenStoryline is an AI video editing agent that transforms manual editing into intention-driven directing through natural language …

2026/10/3 9:42:31 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/2 10:36:31 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:35 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/3 9:42:36 阅读更多 →