golang中的函数

x33g5p2x  于2021-11-12 转载在 Go  
字(1.9k)|赞(0)|评价(0)|浏览(444)

函数的语法

func name(param-list) (result-list){
		body
}

实例

// 比较直接的语法
func add1(x int, y int) int {
    return x + y
}

// 同类型的参数(或返回值)可以放在一起,最后面声明一次类型就好
func add2(x, y int) int {
    return x + y
}

// 将返回值也赋予一个变量名,可读性更好
func add3(x, y int) (z int) {
    z = x + y
		// 裸返回,多用于指定了多个返回值名称的场景,在不同的条件下按需赋值,然后直接return
    return
}

调用函数时,必须按顺序提供每一个参数。golang没有提供参数的默认值,也无法指定实参名。

实参是按照值传递的,函数接收到的是参数的副本,所以修改参数并不会影响到实参本身。如果提供的是指针或其它引用类型(如map、slice),则会间接影响实参变量。

golang使用了可变长度的栈,栈的大小最大可以达到1GB,java语言默认是1MB。所以使用golang无须担心Stack Overflow的问题。

返回多个参数

func divide(x, y float64) (float64, error) {
    if y == 0 {
        return 0, errors.New("error: divide 0")
    }

    return x / y, nil
}

如果使用裸返回的话,函数就是这样的。可以看出,裸返回可以消除冗余的代码,但应该在保证代码可读性的前提下使用。

func divide(x, y float64) (result float64, err error) {
    if y == 0 {
        err = errors.New("error: divide 0")
        return
    }
    result = x / y
    return
}

调用函数时,

func main() {
    a, _ := divede(12, 4) // 忽略其中一个参数
    fmt.Println(a)

    b, err := divede(12, 0)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(b)
    }
}

错误处理

在函数调用时,习惯上将错误值作为以后一个结果返回。

如果错误只有一种情况,结果通常设置为布尔值,可以说明有错误还是没有错误。如果错误的结果有很多种,则类型往往是error。

与其它语言不同,golang通过使用普通值而非异常来报告错误,使用if和return来应对错误,尽管golang有异常机制。这样可以避免冗长的异常堆栈信息。人们说一个人需要有一个横屏的显示器和竖屏的显示器,才能完整显示一个java的异常堆栈。

golang中的惯例是,先做错误检查再处理正常逻辑,如果捕获到了错误,则函数返回。而成功的逻辑一般不放在else中,而是放在外层的作用域中。所以函数的开头一般有一连串的检查用来返回错误,之后才是正常逻辑。

函数变量匿名函数

按照编程语言的管理,通过func定义的函数名称,如果加了括号,就是函数调用,如果不加括号,就是函数变量,go语言也是这样的。

// devide 如果不加括号,就是一个函数变量,函数变量还可以赋值给另外一个函数变量
var f = divide			
x, _ := f(2, 4)

既然函数可以是一个变量,那就可以省略声明变量的这一步,直接编写函数,尤其是当作为另一个函数参数来传递时,例如,先定义一个函数,它的第二个参数是函数类型

func changeNumber(numbers []int, f func(input int) int) {
    for i, number := range numbers {
        numbers[i] = f(number)
    }
}

下面我调用了两次changeNumber,分别传递了不同的匿名函数

numbers := []int{1, 2, 3, 4, 5}
changeNumber(numbers, func(input int) int { return input * 2 })
fmt.Println(numbers)				// [2 4 6 8 10]

numbers2 := []int{1, 2, 3, 4, 5}
changeNumber(numbers2, func(input int) int { return input - 1 })
fmt.Println(numbers2)				// [0 1 2 3 4]

变长函数

func sum(vars ...int) (total int) {
    for _, item := range vars {
        total += item
    }
    return
}

fmt.Println(sum(1, 2, 3, 4, 5))

变长参数的类型是...int,但在函数内部,变长参数的类型是slice。不过,它与[]int类型的函数也不是同样类型的函数。

相关文章