Go 函数

目录

一、函数是一等功公民

1、与其它主要编程语言的差异

2、slice、 map、channel 会有传引用的错觉

3、为什么函数在 Go 语言里面是一等公民

4、函数可以有多个返回值

5、函数作为参数值和返回值

6、自定义类型

二、可变长参数

1、求和函数

三、defer 延迟执行函数


一、函数是一等功公民

1、与其它主要编程语言的差异

  • 可以有多个返回值;
  • 所有参数都是值传递,slice、 map、channel 会有传引用的错觉;
  • 函数可以作为变量的值;
  • 函数可以作为参数和返回值。

2、slice、 map、channel 会有传引用的错觉

当我们把 slice、 map、channel 传过去后,修改了里面的值,外面也能感受到,这就让我们感觉传递的是引用而不是值,那是因为像切片它本身只是一个数据结构,这个数据结构里面包含了指向一段儿连续存储空间的指针,所以说即便是在传值的情况下,它的值被复制到其它函数里了,当我们去修改切片的某个值时,其实操作的是同一块儿存储空间,所以就有一种传引用的错觉。

3、为什么函数在 Go 语言里面是一等公民

函数可以作为变量的值,作为参数和返回值可以很大程度的简化我们的程序并创造一些十分友好的使用方式。

4、函数可以有多个返回值

package _func

import (
	"math/rand"
	"testing"
)

func TestFun(t *testing.T) {
	number1, number2 := returnMultiValues()

	t.Log(number1, number2)	//31 87
}

//函数有多个返回值
//花括号的前面用小括号定义好返回值的类型
func returnMultiValues() (int, int) {
	return rand.Intn(50), rand.Intn(100)
}

5、函数作为参数值和返回值

package _func

import (
	"fmt"
	"testing"
	"time"
)


//计算函数的花费时长,将函数作为参数,函数作为返回值
//这个函数有点像装饰器模式,就是在运行函数的前后加上了计时功能
func timeSpend(inner func(op int) int) func(op int) int  {
	return func(op int) int {
		//开始时间
		start := time.Now()

		//运行这个函数
		ret := inner(op)

		//打印函数的运行时长
		fmt.Println("time spend:", time.Since(start).Seconds())

		//返回值仍然是个函数
		return ret
	}
}

//这是一个慢函数
func slowFunc(op int) int {
    //sleep两秒
	time.Sleep(time.Second * 2)
	return op * op
}


func TestFun(t *testing.T) {
	//将函数传给 timeSpend() 函数作为参数,返回值是具有即时功能的一个函数
	timeSpendSlowFunc := timeSpend(slowFunc)

	//运行这个具有计时功能的函数
	slowFuncRes := timeSpendSlowFunc(10)
	t.Log(slowFuncRes)

	//执行结果:
	//time spend: 2.001692741
	//func_test.go:51: 100
}

6、自定义类型

通过自定义类型,很多比较长的参数可以被大大简化,让我们的程序更加简洁可读。例如上面的timeSpend() 函数,它的参数也是一个函数,看起来比较长,我们可以通过自定义类型来简化。

package custom_type

import (
	"fmt"
	"testing"
	"time"
)

//timeSpend()的参数是一个方法,方法太长,不利于阅读,我们可以自定义类型,
//我们也可以把它理解为一个别名
type IntConversionFun func(op int) int

//通过自定义类型,timeSpend() 的参数就被大大简化了,让我们的程序更加简洁可读
func timeSpend(inner IntConversionFun) IntConversionFun  {
	return func(op int) int {
		//开始时间
		start := time.Now()

		//运行这个函数
		ret := inner(op)

		//打印函数的运行时长
		fmt.Println("time spend:", time.Since(start).Seconds())

		//返回值仍然是个函数
		return ret
	}
}

//这是一个慢函数
func slowFunc(op int) int {
	//sleep两秒
	time.Sleep(time.Second * 2)
	return op * op
}


func TestFun(t *testing.T) {

	//将函数传给 timeSpend() 函数作为参数,返回值是具有即时功能的一个函数
	timeSpendSlowFunc := timeSpend(slowFunc)

	//运行这个具有计时功能的函数
	slowFuncRes := timeSpendSlowFunc(10)
	t.Log(slowFuncRes)

	//执行结果:
	//time spend: 2.001692741
	//func_test.go:51: 100
}

二、可变长参数

1、求和函数

package _func

import (
	"testing"
)

//可变长参数,求和
//用三个点儿代表多个参数
func Sum(opts ...int) int {
	sum := 0
	for _, op :=range opts {
		sum += op
	}

	return sum
}

func TestVarParams(t *testing.T) {
	total := Sum(1, 2, 3, 4)

	t.Log(total)
}

三、defer 延迟执行函数

package _func

import (
	"fmt"
	"testing"
)

//清理释放资源
func clearResources(){
	fmt.Println("This func will clear resources.")
}

//defer 延迟执行函数
func TestDefer(t *testing.T) {
	//defer 后面的函数将会在其它语句都执行完毕后,在 return 之前才会执行。
	//利用这个特性,我们可以用来在函数运行完毕后释放资源。
	defer clearResources()

	//当有多个 defer 函数是,后面的 defer 函数会比前面的 defer 函数先执行
	defer func() {
		t.Log("Another defer func. ")
	}()

	t.Log("This code's position is after defer, but it will run before defer")

	//panic 用来抛出 Go 语言无法修复的错误。
	//即便是抛出了 panic 错误,defer 依旧会执行
	panic("Fatal err")

	//panic 后面的代码将不会被执行,还会报 Unreachable 的提示
	t.Log("This code is after panic, it will not be run")
}

 

:这篇博文是我学习中的总结,如有转载请注明出处:

https://blog.csdn.net/DaiChuanrong/article/details/118047179

上一篇Go字符串

下一篇Go面向对象-行为的定义和实现

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值