Go学习笔记——第4章 函数

本文是关于Go语言中函数的详细笔记,涵盖函数定义、参数、返回值、匿名函数和闭包、延迟调用以及错误处理。Go函数不支持默认参数、命令嵌套定义和重载,但支持多返回值、不定长变参和命名返回值。错误处理通常通过返回error接口类型实现。
摘要由CSDN通过智能技术生成

4.1 定义

使用关键字 func定义函数。函数有一下特点:

  • 无须前置声明
  • 不支持命令嵌套定义
  • 不支持同名函数重载
  • 不支持默认参数
  • 支持不定长变参
  • 支持多返回值
  • 支持命名返回值
  • 支持匿名函数和闭包

函数属于第一类对象,具备相同签名(参数以及返回值列表)的视作同一类型

func main() {
	f := hello
	exec(f)

}

func hello() {
	println("hello, world!")
}

func exec(f func()) {
	f()
}

从阅读和代码维护的角度,使用命令类型更加方便

//定义函数类型
type FormatFunc func(string, ...interface{}) (string, error)

//如果不使用命令类型,这个参数签名会长到没法看
func format(f FormatFunc, s string, a ...interface{}) (string, error) {
	return f(s, a...)
}

建议命名规则

在避免冲突的情况下,函数命名要本着精简短小、望文知意的原则。

  • 通常是动词和介词加上名词,例如scanWords。

  • 避免不必要的缩写,printError 要比printErr更好一些。

  • 避免使用类型关键字,比如buildUserStruct看上去会很别扭。

  • 避免歧义,不能有多种用途的解释造成误解。

  • 避免只能通过大小写区 分的同名函数。

  • 避免与内置函数同名,这会导致误用。

  • 避免使用数字,除非是特定专有名词,例如UTF8。

  • 避免添加作用域提示前缀。

  • 统一使用camel/pascal case拼写风格。

  • 使用相同术语,保持一 致性。

  • 使用习惯用语,比如init表示初始化,is/has返回布尔值结果。

  • 使用反义词组命名行为相反的函数,比如get/set. min/max等。

4.2 参数

Go不支持默认值的可选参数,不支持命令实参。调用时,必须按照签名顺序传递指定类型和数量的实参。

在参数列表中,相邻对的同类型参数可以合并。

func test(x, y int, s string, _ bool) *int {
	return nil
}

参数可视作函数局部变量,因此不能再相同层次定义同名变量

func add(x, y int) int {
	x := 10		//错误语法
	var y int	//错误语法 
	return x * y
}

形参是函数定义中的参数,实参是函数调用时所传递的和参数。形参类似函数局部变量,实参则是函数的外部对象。可以是常量、变量、表达式或者函数等。

不管是指针、引用类型,还是其他参数类型,都是值拷贝传递。区别无非是拷贝目标对象,还是拷贝指针。在函数调用前,会为形参和返回值分配内存空间,并将实参拷贝到形参内存。

变参

变参本质就是一个切片。只能接收到一个到多个同类型的参数,且必须放到列表的尾部。

func main() {
	test("abc",1, 2, 3, 4)
}

func test(s string, a ...int) {
	fmt.Printf("%T,%v\n", a, a)
}

//运行结果
[]int,[1 2 3 4]

4.3 返回值

有返回值的函数,必须有明确的return终止语句。除非有panic,或者无break的死循环,则无须终止语句。可以使用_忽略不想要的返回值。

可以有多个返回值,又是error模式

func div(x, y int) (int, error){
	if y == 0 {
		return 0, errors.New("division by zero")
	}
	
	return x / y , nil
}

命名返回参数

func paing(sql string, index int) (count int, pages int, err error)

命令返回参数和参数一样,可以当做函数局部变量使用,最后由return隐式返回。

func div(x, y int) (z int, err error){
	if y == 0 {
		err = errors.New("division by zero")
		return
	}
	
	z = x / y
	return     //相当于 "return z, nil"
}

4.4 匿名函数

匿名函数是指没有定义名字符号的函数。除了没有名字,匿名函数和普通函数完全一样。最大的区别是我们可以再函数内部定义匿名函数,形成类似嵌套的效果。

func main() {
	func(s string){
		println(s)
	}( "hello")
}

闭包
闭包是指上下文中引用了自由变量的函数,或者说是函数和其引用的环境的组合体。

4.5 延迟调用

语句defer向当前函数注册稍后执行的函数调用。这些调用被称作延迟调用,因为他们直到当前函数执行结束前才被执行。常用于资源释放、解除锁定以及错误处理等操作。

func main() {

	f, err := os.Open("./main.go")
	if err != nil {
		log.Fatalln(err)
	}	
	defer f.Close()
	... do something ...
}

4.6 错误处理

error
官方推荐的标准做法是返回error状态

func Scanln(a....interface{}) (n int, err error)

标注库将error定义为接口类型,以便实心自定义错误类型。

type error interface {
	Error() string
}

按照惯例,error总是最后一个返回参数。标准库提供了相关创建函数,可方便地创建包含简单错误文本的error对象

var errDivByZero = errors.New("division by zero")
func main() {

	z, err := div(5, 0)
	if err == errDivByZero {
		log.Fatalln(err)
	}
	println(z)
}


func div(x, y int) (int, error){
	if y == 0 {
		return 0, errDivByZero
	}

	return x / y , nil
}

建议:除非是不可恢复、导致系统无法正常工作的错误,否则不建议使用painc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值