Golang 函数【防备忘】

本文探讨了如何利用Go语言的特性提高代码效率,包括缓存、时空权衡、参数传递方式、非命名和命名返回值、变长参数、defer的使用场景、内置函数的应用以及闭包和斐波那契数列的实现。同时,介绍了如何通过闭包进行调试和计算函数运行时间,揭示了Go语言在函数操作和效率优化上的强大能力。
摘要由CSDN通过智能技术生成

Golang 函数

  • 提升效率(减少时间开销),最直接有效的方法就是避免重复计算
  • 将之前计算过的结果,保存下来,放入缓存(空间开销加大)
  • 时空互换,真理啊,淦!
  1. 允许这样进行
假设 f1 需要 3 个参数 f1(a, b, c int),
同时 f2 返回 3 个参数 f2(a, b int) (int, int, int),
就可以这样调用 f1:f1(f2(a, b))。
这个有点意思
  1. 按值传递(call by value) 按引用传递(call by reference)
这个个意思都懂,就不再赘述了
切片(slice)、字典(map)、接口(interface)、通道(channel)这样的引用类型都是默认使用引用传递(即使没有显式的指出指针)
  1. 非命名返回值与命名返回值
非命名返回值
func func1() (int,int){  //func func1() int 这种的非命名的,只有一个返回值,可以不加括号
	temp1:=1+1
	temp2:=2+2
	return temp1,temp2
}
命名返回值
func func2() (n1 int,n2 int){  //func func2() (n2 int) 这种命名的,只有一个返回值,也要加括号
	n1 = 1+1
	n2 = 2+2
	return
}
  1. 传递变长参数(类型相同)
obj := [...]int{1,2,3,4,5,6}
slcie := obj[:]
func1(slice...)   //注意实参如何传入

func func1(slice ...int) {     //注意参数如何写
	...
}
  1. 传递变长参数(类型不相同)
①结构体
②使用默认的空接口 interface{}
  1. defer
推迟执行
推迟到函数返回之前(或任意位置执行 return 语句之后)一刻才执行某个语句或函数
**注意defer语句,执行在return语句执行之后,如果defer中含有返回值变量,这一点很重要了**
**若有多个defer函数被注册,则按照逆序输出,栈的道理**
  1. defer的用处
1.关闭文件流 
2.解锁一个加锁的资源
3.打印最终报告
4.关闭数据库链接
5.defer 语句实现代码追踪
func trace(s string)   { fmt.Println("entering:", s) }  //进入函数时,执行
func untrace(s string) { fmt.Println("leaving:", s) }  //然后defer 离开函数
6.defer 语句来记录函数的参数与返回值
func func1(s string) (n int, err error) {
defer func() {
     log.Printf("func1(%q) = %d, %v", s, n, err)
  }()
  ...
}
  1. 内置函数
    11
  2. 函数作形参
一、函数作实参
func isMax(a,b int){
}
func reTwonum(a int) (int,int){
}
调用:isMax(33,77)  or    isMax(reTwonum(55))
二、
func isMax(a int,f func(int)(int,int)) int{   //注意函数形参书写方式,有反返回值的话,也要带上
	return a*f(a)
}
func reTwonum(a int) (int,int){
}
调用:isMax(5,reTwonum)   //注意函数实参如何传入,只需要写函数名即可
  1. 闭包
一、无参闭包
func() {
	...
}()
二、带参闭包
func(a int){
	...
}(9)
三、闭包赋值给变量
vR:=func(a int){
	...
}           //用变量接收了,这里就没有括号了
调用:vR(9)
  1. 应用闭包:将函数作为返回值(叠加、拼接)
一、无参函数,将闭包作为返回值
func Add2() func(b int) int {
    return func(b int) int {   //注意写法
        return b + 2
    }
}
调用:
g2:=Add2()   //这一句下来,即执行了Add2函数,又将Add2中的闭包(也就是返回值函数)传递给了参数g2
fmt.Printf("%d",g2(2))   //此时,实参2对标b int传入闭包

二、带参函数,将函数作为返回值
func Adder(a int) func(b int) int {
    return func(b int) int {
        return a + b
    }
}
调用:
g2:=Adder(1)  //这一句下来,实参1对标a int传入Adder函数,将Adder中的闭包传递给g2
fmt.Prinf("%d",g2(2))  //此时,实参2对标闭包的b int传入闭包

三、参数寿命问题***
func main() {
    var f = Adder()
    fmt.Print(f(1), " - ")
    fmt.Print(f(20), " - ")
    fmt.Print(f(300))
}

func Adder() func(int) int {
    var x int    //注意这个变量
    return func(delta int) int {
        x += delta
        return x
    }
}
输出为:1-21-321
通过这个结果可以发现,f接收Adder的返回值闭包之后,f也保留了里面的变量x,并且会随着f的存在一直存在
不会应为某一次f(*)的调用,而重置x的大小
func Adder(x int) func(int) int 这样也是同样的道理,x作为形参或者直接在内部定义都是一样的效果
  1. 闭包应用:斐波那契数列
func fibonacci() func() int {
	froval := 0
	postval := 1
	return func() int {
		tempval := froval
		froval = postval
		postval += tempval
		return froval
	}
}
func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
}
  1. 使用闭包调试
//用到了在加强
	where := func() {
		_, file, line, _ := runtime.Caller(1)
		log.SetFlags(log.Llongfile)
		log.Printf("%s:%d", file, line)
	}
	where()
	// some code
	where()
	// some more code
	where()
  1. 计算函数运行时间
start := time.Now()
longCalculation()   //自己的函数
end := time.Now()
delta := end.Sub(start)
fmt.Printf("longCalculation took this amount of time: %s\n", delta)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋山刀名鱼丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值