⑤ 函数

本文即将看到:
⚬ --- 函数
⚬ --- defer
⚬ --- 高阶函数

一、函数

  1. 格式
func name (形参 type,形参 type) (返回值类型){
	return value1,value2
}
func name (形参,形参,形参  type) (标识符,标识符,标识符 返回值类型){
	return
} //简写 
  1. 参数
    arg...type 可变参
func name(arg...int){
	return
}
  1. 参数传递 值传递 引用传递
● 传指针使得多个函数能操作同一个对象
● Go语言中slicemap这三种类型的实现机制类似指针,所以可以直接传递,而不用取地址后传递指针。(注:若函数需改变slice的长度,则仍需要取地址传递指针)
  1. 返回值
● 函数被调用后,返回给调用处的执行结果,叫做函数的返回值。
● 函数可以没有返回值,也可以有一个返回值,也可以有返回多个值。
● _ 是Go中的空白标识符。它可以代替任何类型的任何值。
  1. 变量作用域
● 全局变量: 函数外部定义的变量,就叫做全局变量
  作用范围: 整个程序
● 局部变量: 函数内部定义的变量,就叫做局部变量. 
  作用范围: 函数内

二、defer(延迟) 在函数或程序结束前执行,多个defer按逆序执行

● 延迟并不仅仅局限于函数。延迟一个方法调用也是完全合法的。
● 离开所在的方法时,执行(报错的时候也会执行)
● 如果有很多调用defer,那么defer是采用后进先出模式
● 延迟并不仅仅局限于函数。延迟一个方法调用也是完全合法的。

三、高阶函数

  1. 匿名函数 没有名字的函数
● 定义一个匿名函数,直接进行调用。通常只能使用一次。 
● 也可以使用匿名函数赋值给某个函数变量,那么就可以调用多次了。
● 将匿名函数作为另一个函数的参数,回调函数
● 将匿名函数作为另一个函数的返回值,可以形成闭包结构。

示例

	func(){
		fmt.Println("匿名函数")
	}()  // 只能调用一次

	fun2 := func() {
		fmt.Println("我也是啊!")
	}  //可以调用多次
	fun2()
	fun2()

	//带参数的匿名函数
	func(a,b int){
		fmt.Println(a,b)
	}(10,20)

	//带返回值的匿名函数
	res := func(a,b int) int{
		return a+b
	}(10,20)  //匿名函数调用, 将执行结果返回给 res
	fmt.Println(res)

	res2 := func(a,b int) int{
		return a+b
	}                 //将匿名函数的值(地址), 赋给res2
	fmt.Println(res2)

	fmt.Println(res2(100,100))

运行结果: 
        匿名函数
        我也是啊!
        我也是啊!
        10 20
        30
        0x49aaf0
        200
  1. 回调函数 将一个函数fun2作为函数fun1的一个参数。那么fun2叫做回调函数,fun1叫做高阶函数。

示例

func add(c,d int)int{
	return c + d
}

func hOper(a,b int, fun func(int,int)int )int{
	fmt.Println(a,b,fun)
	res := fun(a,b)
	return res
}
func main(){
	res := hOper(100,200,add)
	fmt.Println(res)
}

运行结果:
        100 200 0x49a7b0
        300
  1. 闭包
● 一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量(外层函数中的参数,或者外层函数中 
  直接定义的变量),并且该外层函数的返回值就是这个内层函数。
● 这个内层函数和外层函数的局部变量,统称为闭包结构。

注意:
● 局部变量的生命周期会发生改变,正常的局部变量随着函数调用而创建,随着函数的结束而销毁。但是闭包结构中 
  的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还要继续使用。

示例

package main

import "fmt"

func closure()func()int{
	i := 0
	res := func()int{
		i++
		return i
	}
	return res
} // 闭包

func main(){
	res := closure()

	a := res()
	fmt.Println(a)

	fmt.Println(res())
	fmt.Println(res())

	res2 := closure() //新开辟空间
	b := res2()
	fmt.Println(b)
	fmt.Println(res2())
}
执行结果:
        1
        2
        3
        1
        2
posted @   Gonfei  阅读(118)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示