Golang的函数

📅 2026/6/23 11:55:22
Golang的函数
函数是Go语言中的基本构建块用于组织可重用的代码逻辑。本文将详细介绍Go中函数的定义、参数传递、返回值以及高级用法。1. 函数的基本格式完整语法结构func函数名(参数列表)(返回值列表){// 函数体return返回值}组成部分说明组成部分说明是否必需func函数关键字必需函数名标识函数名称必需参数列表(参数名 参数类型, ...)可选返回值列表(返回值名 返回值类型, ...)可选函数体{ ... }必需return返回语句根据返回值类型决定2. 函数的参数传递Go语言中的参数传递分为两种方式值传递和引用传递。值传递值传递会将实参的值复制一份传递给函数函数内部对参数的修改不会影响外部变量。示例代码packagemainimportfmtfuncmain(){x:12fmt.Printf(进入函数前,函数外部x的值为:%d\n,x)add(x)fmt.Printf(进入函数后,函数外部x的值还是:%d\n,x)}funcadd(xint)int{x12fmt.Printf(函数内部,x完成加12,值为:%d\n,x)returnx}输出进入函数前,函数外部x的值为:12 函数内部,x完成加12,值为:24 进入函数后,函数外部x的值还是:12原理分析外部变量 x 12 | | 值传递复制一份 12 ↓ 函数参数 x 12 (独立副本) | | 函数内部修改 ↓ 函数内部 x 24 | | 函数结束后副本销毁 ↓ 外部变量 x 12 (不受影响)引用传递引用传递通过传递变量的内存地址指针函数内部通过指针修改数据会直接影响外部变量。示例代码packagemainimportfmtfuncmain(){x:12fmt.Printf(进入函数前,函数外部x的值为:%d\n,x)add2(x)// 传递x的内存地址fmt.Printf(进入函数后,函数外部x的值变为:%d\n,x)}funcadd2(x*int)int{*x12// 通过指针修改值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{returnab}// 连续参数类型可以简写funcadd(a,bint)int{returnab}可变参数funcsum(nums...int)int{total:0for_,num:rangenums{totalnum}returntotal}// 调用方式result:sum(1,2,3,4,5)// result 154. 函数的返回值单返回值funcadd(aint,bint)int{returnab}多返回值funcdivide(a,bint)(int,error){ifb0{return0,fmt.Errorf(除数不能为零)}returna/b,nil}命名返回值funcgetCoordinates()(x,yint){x10y20return// 裸返回自动返回x和y}5. 匿名函数和闭包匿名函数// 定义并立即执行funcmain(){result:func(a,bint)int{returnab}(10,20)fmt.Println(result)// 30}闭包ClosurefuncgetCounter()func()int{count:0returnfunc()int{countreturncount}}funcmain(){counter:getCounter()fmt.Println(counter())// 1fmt.Println(counter())// 2fmt.Println(counter())// 3}6. 函数作为类型定义函数类型typeOperationfunc(int,int)intfuncadd(a,bint)int{returnab}funcsubtract(a,bint)int{returna-b}funcmain(){varop Operation opadd fmt.Println(op(10,5))// 15opsubtract 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函数在包初始化时自动执行用于初始化包级别的变量。packagemainimportfmtfuncinit(){fmt.Println(init函数执行)}funcmain(){fmt.Println(main函数执行)}// 输出// init函数执行// main函数执行9. 完整示例程序packagemainimportfmtfuncmain(){// 值传递示例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{x12fmt.Printf(函数内部,x完成加12,值为:%d\n,x)returnx}// 引用传递函数指针funcadd2(x*int)int{*x12fmt.Printf(函数内部,x完成加12,值为:%d\n,*x)return*x}// 多返回值函数funcdivide(a,bint)(int,int){returna/b,a%b}// 闭包函数funcgetCounter()func()int{count:0returnfunc()int{countreturncount}}函数命名使用驼峰命名法导出函数首字母大写单一职责每个函数只做一件事参数数量尽量避免超过5个参数错误处理多返回error类型进行错误处理避免副作用尽量保持函数的纯粹性适当注释为导出的函数添加注释说明