尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Golang的函数

Golang的函数
📅 发布时间:2026/6/23 12:08:01

函数是Go语言中的基本构建块,用于组织可重用的代码逻辑。本文将详细介绍Go中函数的定义、参数传递、返回值以及高级用法。

1. 函数的基本格式

完整语法结构

func函数名(参数列表)(返回值列表){// 函数体return返回值}

组成部分说明

组成部分说明是否必需
func函数关键字必需
函数名标识函数名称必需
参数列表(参数名 参数类型, ...)可选
返回值列表(返回值名 返回值类型, ...)可选
函数体{ ... }必需
return返回语句根据返回值类型决定

2. 函数的参数传递

Go语言中的参数传递分为两种方式:值传递和引用传递。

值传递

值传递会将实参的值复制一份传递给函数,函数内部对参数的修改不会影响外部变量。

示例代码
packagemainimport"fmt"funcmain(){x:=12fmt.Printf("进入函数前,函数外部x的值为:%d\n",x)add(x)fmt.Printf("进入函数后,函数外部x的值还是:%d\n",x)}funcadd(xint)int{x+=12fmt.Printf("函数内部,x完成加12,值为:%d\n",x)returnx}

输出:

进入函数前,函数外部x的值为:12 函数内部,x完成加12,值为:24 进入函数后,函数外部x的值还是:12

原理分析:

外部变量 x = 12 | | 值传递:复制一份 12 ↓ 函数参数 x = 12 (独立副本) | | 函数内部修改 ↓ 函数内部 x = 24 | | 函数结束后副本销毁 ↓ 外部变量 x = 12 (不受影响)

引用传递

引用传递通过传递变量的内存地址(指针),函数内部通过指针修改数据会直接影响外部变量。

示例代码
packagemainimport"fmt"funcmain(){x:=12fmt.Printf("进入函数前,函数外部x的值为:%d\n",x)add2(&x)// 传递x的内存地址fmt.Printf("进入函数后,函数外部x的值变为:%d\n",x)}funcadd2(x*int)int{*x+=12// 通过指针修改值fmt.Printf("函数内部,x完成加12,值为:%d\n",*x)return*x}

输出:

进入函数前,函数外部x的值为:12 函数内部,x完成加12,值为:24 进入函数后,函数外部x的值变为:24

原理分析:

外部变量 x = 12 (内存地址: 0x1000) | | 引用传递:传递地址 0x1000 ↓ 函数参数 x = 0x1000 (指针) | | 通过地址修改内存 ↓ *操作符解引用,修改地址0x1000的值 | ↓ 外部变量 x = 24 (同一块内存被修改)

值传递 vs 引用传递对比

对比维度值传递引用传递(指针)
传递内容数据的副本数据的内存地址
内存占用复制整个数据只复制指针(8字节)
修改影响不影响外部变量影响外部变量
大对象性能开销较大开销较小
安全性高(不会意外修改外部数据)需要谨慎使用
语法标识直接传值使用&取地址和*解引用

3. 函数的参数类型

多个参数

funcadd(aint,bint)int{returna+b}// 连续参数类型可以简写funcadd(a,bint)int{returna+b}

可变参数

funcsum(nums...int)int{total:=0for_,num:=rangenums{total+=num}returntotal}// 调用方式result:=sum(1,2,3,4,5)// result = 15

4. 函数的返回值

单返回值

funcadd(aint,bint)int{returna+b}

多返回值

funcdivide(a,bint)(int,error){ifb==0{return0,fmt.Errorf("除数不能为零")}returna/b,nil}

命名返回值

funcgetCoordinates()(x,yint){x=10y=20return// 裸返回,自动返回x和y}

5. 匿名函数和闭包

匿名函数

// 定义并立即执行funcmain(){result:=func(a,bint)int{returna+b}(10,20)fmt.Println(result)// 30}

闭包(Closure)

funcgetCounter()func()int{count:=0returnfunc()int{count++returncount}}funcmain(){counter:=getCounter()fmt.Println(counter())// 1fmt.Println(counter())// 2fmt.Println(counter())// 3}

6. 函数作为类型

定义函数类型

typeOperationfunc(int,int)intfuncadd(a,bint)int{returna+b}funcsubtract(a,bint)int{returna-b}funcmain(){varop Operation op=add fmt.Println(op(10,5))// 15op=subtract fmt.Println(op(10,5))// 5}

函数作为参数

funccalculate(a,bint,opfunc(int,int)int)int{returnop(a,b)}funcmain(){result:=calculate(10,5,func(a,bint)int{returna*b})fmt.Println(result)// 50}

7. defer延迟执行

defer语句用于在函数返回前执行某些操作,常用于资源清理。

funcreadFile(){file,err:=os.Open("test.txt")iferr!=nil{return}deferfile.Close()// 函数返回前自动关闭文件// 读取文件内容...fmt.Println("读取文件成功")}

defer的特性

  • 多个defer按后进先出(LIFO)顺序执行
  • defer在函数返回之前执行
  • defer的参数在定义时就已经确定
funcdeferExample(){deferfmt.Println("第三")deferfmt.Println("第二")deferfmt.Println("第一")fmt.Println("开始执行")}// 输出:// 开始执行// 第一// 第二// 第三

8. init函数

init函数在包初始化时自动执行,用于初始化包级别的变量。

packagemainimport"fmt"funcinit(){fmt.Println("init函数执行")}funcmain(){fmt.Println("main函数执行")}// 输出:// init函数执行// main函数执行

9. 完整示例程序

packagemainimport"fmt"funcmain(){// 值传递示例fmt.Println("=== 值传递 ===")x:=12fmt.Printf("进入函数前,函数外部x的值为:%d\n",x)add(x)fmt.Printf("进入函数后,函数外部x的值还是:%d\n\n",x)// 引用传递示例fmt.Println("=== 引用传递 ===")y:=12fmt.Printf("进入函数前,函数外部y的值为:%d\n",y)add2(&y)fmt.Printf("进入函数后,函数外部y的值变为:%d\n\n",y)// 多返回值示例fmt.Println("=== 多返回值 ===")quotient,remainder:=divide(17,5)fmt.Printf("17 / 5 = %d 余 %d\n\n",quotient,remainder)// 闭包示例fmt.Println("=== 闭包示例 ===")counter:=getCounter()fmt.Println(counter())fmt.Println(counter())fmt.Println(counter())}// 值传递函数funcadd(xint)int{x+=12fmt.Printf("函数内部,x完成加12,值为:%d\n",x)returnx}// 引用传递函数(指针)funcadd2(x*int)int{*x+=12fmt.Printf("函数内部,x完成加12,值为:%d\n",*x)return*x}// 多返回值函数funcdivide(a,bint)(int,int){returna/b,a%b}// 闭包函数funcgetCounter()func()int{count:=0returnfunc()int{count++returncount}}
  1. 函数命名:使用驼峰命名法,导出函数首字母大写
  2. 单一职责:每个函数只做一件事
  3. 参数数量:尽量避免超过5个参数
  4. 错误处理:多返回error类型进行错误处理
  5. 避免副作用:尽量保持函数的纯粹性
  6. 适当注释:为导出的函数添加注释说明

相关新闻

  • 2026AI命理软件好用吗?八字排盘App辅助分析要看依据和边界
  • InDraw如何将化合物的名称转为结构式?
  • 网络管理作业

最新新闻

  • GitHub周趋势2026W25 | Headroom 压缩 95% Token、NVIDIA 开源 AI Agent 安全扫描器、Apple macOS 原生 Linux 容器、…
  • 2010年-2024年上市公司参与数字技术标准制定情况
  • ATF1508AS(L) CPLD开发全解析:从硬件架构到JTAG调试实战
  • ATA6824C电机驱动芯片:H桥驱动、电荷泵与热保护机制详解
  • 哔咔漫画下载器:打造您的个人离线漫画图书馆
  • 15.1 | 潜江模式:潜龙一号全链条AI平台架构解析

日新闻

  • Arduino-ESP32项目深度解析:解锁隐藏芯片支持与架构演进
  • 2026年 系统窗厂家/品牌推荐榜单:隔音系统窗+高端系统门窗的核心优势与选购指南 - 品牌发掘
  • NVBench:首个双语非言语发声语音合成评测基准详解与实践

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号