Go学习笔记(四)

3.函数

3.1函数定义

3.2变参

3.3返回值

3.4匿名函数

3.5延迟调用

3.6错误处理


1.函数是第一类对象,可作为参数传递。建议将复杂签名定义为函数类型,以便于阅读。

package main

import "fmt"

func test(fn func() int) int {
    return fn()
}

type FormatFunc func(s string, x,y int) string //定义函数原型

func format(fn FormatFunc,s string, x,y int) string {
    return fn(s,x,y)
}

func main() {
    s1:=test(func() int {return 100}) //直接将匿名函数当参数
    
    s2:=format(func(s string,x,y int)string {
        return fmt.Sprintf(s,x,y)
    },"caonima %d,%d rinidie",10,20)

    fmt.Println(s1,s2)//输出:100 caonima 10,20 rinidie
    
}


2.变参本质上就是 slice。只能有一个,且必须是最后一个。

func test(s string, n ...int) string {
var x int
for _, i := range n {
x += i
}
return fmt.Sprintf(s, x)
}
func main() {
println(test("sum: %d", 1, 2, 3))
}
使用slice对象做变参时,必须展开。

func main() {
s := []int{1, 2, 3}
println(test("sum: %d", s...))
}


3. 不能用容器对象接收多返回值。只能用多个变量,或 "_" 忽略。 

func test() (int, int) {
return 1, 2
}
func main() {
// s := make([]int, 2)
// s = test() // Error: multiple-value test() in single-value context
x, _ := test()
println(x)
}

4.命名返回参数允许defer延迟调用通过闭包读取和修改

func add(x, y int) (z int) {
defer func() {
z += 100
}()
z = x + y
return
}
func main() {
println(add(1, 2)) // 输出: 103
}

显示return返回前,会先修改命名返回参数。

func add(x, y int) (z int) {
defer func() {
println(z) // 输出: 203
}()
z = x + y
return z + 200 // 执⾏顺序: (z = z + 200) -> (call defer) -> (ret)
}
func main() {
println(add(1, 2)) // 输出: 203
}

5.匿名函数可赋值给变量,做为结构字段,或者在 channel 里传送。

// --- function variable ---
fn := func() { println("Hello, World!") }
fn()
// --- function collection ---
fns := [](func(x int) int){
func(x int) int { return x + 1 },
func(x int) int { return x + 2 },
println(fns[0](100))
// --- function as field ---
d := struct {
fn func() string
}{
fn: func() string { return "Hello, World!" },
}
println(d.fn())
// --- channel of function ---
fc := make(chan func() string, 2)
fc <- func() string { return "Hello, World!" }
println((<-fc)())



6.关键字 defer 用于注册延迟调用。这些调用直到 ret 前才被执行,通常用于释放资源或错误处理。 

多个 defer 注册,按 FILO 次序执行。哪怕函数或某个延迟调用发生错误,这些调用依旧会被执行。

func test(x int) {
defer println("a")
defer println("b")
defer func() {
println(100 / x) // div0 异常未被捕获,逐步往外传递,最终终⽌进程。
}()
defer println("c")
}
func main() {
test(0)
}

输出:
c b a
panic: runtime error: integer divide by zero



7..没有结构化异常,使用 panic 抛出错误, recover 捕获错误。

func test() {
    
    defer func(){
        if err:=recover();err!=nil{
            fmt.Println(err.(string))
        }
    }()

    panic("panic error")

}

延迟调用中引发的错误,可被后续延迟调用捕获,但仅最后一个错误可被捕获。
捕获函数 recover 只有在延迟调用内直接调用才会终止错误,否则总是返回 nil。任何未捕获的错误都会沿调用堆栈向外传递。
导致关键流程出现不可修复性错误的使用panic,其他使用 error





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值