1.匿名函数
在 Go 编程语言中,匿名函数是一种没有函数名的函数。它们通常被用作函数字面值(Function Literals)或闭包(Closures),以便在需要的地方直接定义和使用函数。
创建一个匿名函数的语法如下:
func() {
// 函数体
}
匿名函数的一个重要特性是能够访问其外部作用域中的变量。这种行为称为闭包。下面是一个使用闭包的示例:
package main
import "fmt"
func main() {
x := 5
func() {
x = 6
fmt.Println(x) // 6
}()
fmt.Println(x) // 6
}
在 Go 中,闭包可以访问和修改其引用的变量。这意味着在闭包函数中修改变量的值会影响到原始变量,因为它们共享同一个内存地址。
2.defer/panic/recover
在 Go 编程语言中,defer、panic和recover是被用来处理错误和异常的三个关键字。
defer用于延迟(defer)函数的执行,在当前函数返回之前进行执行。通过defer可以确保一些清理工作得到执行,比如关闭文件或释放资源。defer语句会被添加到一个栈中,按照后进先出(LIFO)的顺序执行。panic用于引发(panic)一场。当某个不可恢复的错误发生时,可以使用panic引发异常。这个异常会导致程序的终止,但是在程序终止之前,panic会沿着调用栈向上传递,直到被recover捕获或到达最顶层函数。recover用于从 panic 中恢复。通常情况下,recover应该在defer函数中使用。它能够捕获 panic,并允许程序继续执行,避免程序终止。如果没有发生 panic 或者 panic 没有被捕获,recover将返回 nil。
package main
import (
"fmt"
)
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
}
}()
fmt.Println("Start")
doSomething()
fmt.Println("End")
}
func doSomething() {
fmt.Println("Doing something...")
panic("Oops, something went wrong!")
fmt.Println("This line will never be executed")
}
在上面的示例中,当 doSomething 函数中的 panic 被触发时,程序会跳转到 main 函数的 defer 语句中的 recover()。然后程序继续执行,并输出 "Recovered: Oops, something went wrong!"。这样就成功地从 panic 中恢复,并继续执行程序。
请注意,panic 和 recover 应该被谨慎使用。通常情况下,应该只在无法处理的错误或者异常情况下使用 panic 和 recover,而不是作为常规的错误处理机制。
3.泛型函数
在Go语言中,泛型函数是一种可以处理多种数据类型的函数。它们可以接受不同类型的参数,并且可以在不同的上下文中使用。这使得我们能够编写更加灵活和通用的代码。
假设我们想编写一个函数,用于比较两个不同类型的值是否相等。我们可以使用泛型函数来实现这个功能,而不需要为每种类型都编写一个单独的函数。
下面是一个简单的泛型函数示例
func Equals[T comparable](a, b T) bool {
return a == b
}
在这个例子中,我们使用了泛型类型参数T,它可以代表任意可比较的类型。函数的参数a和b都是类型为T的值。函数内部的return a == b语句比较了这两个值是否相等,并返回一个布尔值。
使用这个泛型函数,我们可以比较不同类型的值,例如:
fmt.Println(Equals(5, 5)) // 输出: true
fmt.Println(Equals("hello", "world")) // 输出: false
fmt.Println(Equals(3.14, 3.14)) // 输出: true
Go语言中泛型函数的类型参数限定符:
comparable:表示该类型必须是可比较的,也就是说可以使用==和!=进行比较。这个限定符适用于大多数基本类型和自定义类型,只要它们实现了相应的比较操作。any:表示该类型可以是任意类型,没有任何限制。使用any作为类型参数可以接受任何类型的值,但在函数内部无法进行具体的类型操作。numeric:表示该类型必须是数值类型,包括整数、浮点数和复数类型。ordered:表示该类型必须是可排序的,也就是说可以使用<、<=、>和>=进行比较。slice:表示该类型必须是切片类型。map:表示该类型必须是映射类型。channel:表示该类型必须是通道类型。