go-函数

在上一篇博文中,我们介绍了Go里的运算符和流程控制的使用,接下来将记录一下Go里面函数的使用:

设计规则

  • 大写字母开头的变量是可以导出的,也就是其他包可以读取的,是公有变量。小写字母开头的变量是不可导出的,是私有变量
  • 大写字母开头的函数也是一样,相当于class中的带有public关键字的公有函数;小写字母开头的就是有private关键字的私有函数

函数

函数是Go语言中的核心设计,它通过关键字func来进行声明,举个栗子:

package main

import "fmt"

func max(a int, b int) int{
    if a >= b{
        return a
    }else{
        return b
    }
}

func main() {
    fmt.Println(max(10, 5))
}

这里,我们传递两个参数,a、b都是int类型,并且返回一个int类型。接下来,我们定义一个无返回值的函数,如下:

package main
import "fmt"

func print_info(a int, b int){
    fmt.Println(a, b)
}

func main(){
    print_info(10, 5)
}

// 打印结果如下
10 5

在Go中,还支持函数返回多个值,如下:

package main
import "fmt"

func exchange(a int, b int) (int, int) {
    return b, a
}

func main() {
    a := 1
    b := 2
    fmt.Println(exchange(a, b))
}

在函数exchange中,我们可以看到传递的两个参数都是int类型,我们可以将其简化,如下:

func exchange(a, b int) (int, int) {
    return b, a
}

Go语言中,函数还支持变参,接受变参的函数有着不定数量的参数。下面,我们来定义一个接收变参的函数,如下:

package main

import "fmt"

func print_args(args ...int){
    fmt.Printf("args type is %T, length = %d, args = %v", args, len(args), args)
}

func main(){
    print_args(1, 2, 3)
}

// 打印结果如下
args type is []int, length = 3, args = [1, 2, 3]

args ...int表示接收不定长参数,并且参数皆为int类型。从打印结果可以得知,args是一个slice,所以我们可以使用slice的一些操作!不定长参数的位置只能放在最后面,否则将发生编译错误,下面这种定义方式是错误的:

func test(args ..int, a int) {
    ...
}

当有返回值情况,我们还可以定义变量来接收,那么这种情况之下,函数我们可以这样定义:

func test() (a int, b int){
    a, b = 1, 2
    return
}

观察这种写法,可以看出,我们定义了两个变量作为返回值,所以return的时候,无需再进行写出该返回什么,而且a,b已经定义好了,所以我们只需为其赋值即可,所以这里用的是=而不是:=

在Go中,同样可以使用return来终止函数,如下:

func test(){
    for i:=0; i < 1000; i++ {
        if i == 100{
            return
        }
        fmt.Println(i)
    }
    fmt.Println("aaaaaaaaaa")
}

如此,当循环到100时会终止函数,因此aaaaaaaaaa的打印将永远不会执行!

传值与传指针

当我们传一个参数值到被调用函数里面时,实际上是传了这个值的一份Copy,当在被调用函数中修改参数值的时候,调用函数中相应实参不会发生任何变化,因为数值变化只作用在copy上,下面我们举个栗子验证一下:

package main

import "fmt"

func add(a int) int {
    a++
    return a
}

func main() {
    a := 3
    
    fmt.Println(add(a))     // 4
    fmt.Println(a)          // 3
}

如果,有这样的需求,我们在执行某个函数过后,改变其值,这时我们就需要传递一个指针过去。修改后的代码如下:

package main
import "fmt"

func test(x *int) int {
    *x++
    return *x
}

func main() {
    x := 3
    
    fmt.Println(test(&x))
    fmt.Println(x)
}

执行结果如下:

4
4

defer

Go语言中有种不错的设计,即延迟语句。使用延迟语句,可以延迟一个函数的调用,使用方式如下:

package main
import "fmt"

func main() {
    defer fmt.Println("aaaaaaaaaa")
    fmt.Println("bbbbbbbbbb")
}

// 打印结果如下
bbbbbbbbbb
aaaaaaaaaa

值得注意的是,如果一个函数中有多个defer,它会遵循后进先出的原则依次执行,哪怕函数或者某个延迟调用发生错误,这些调用依旧会执行,如下:

package main
import "fmt"

func division(a, b int) (result int){
    result = a / b
    return
}

func main() {
    defer fmt.Println("aaaaaaaaaa")
    defer fmt.Println("bbbbbbbbbb")
    defer division(10 ,0)
    defer fmt.Println("cccccccccc")
}

上面代码将会依次打印“cccccccccc”、“bbbbbbbbbb”、“aaaaaaaaaa”,最后程序崩溃

函数别名

我们还可以像基本类型一样,给函数起一个别名,并进行初始化,如下:

package main

import "fmt"

type MyFunc func(int, int) int

func add(a, b int) int{
    return a + b
}

func main(){
    var f Myfunc
    f = add
    
    fmt.Println(f(1, 2))    // 3
}

下面我们来进行分析一下代码:首先定义了一个函数别名,该函数具有两个参数而且都为int类型,并具有一个返回值也是int类型!在main函数中,声明了一个变量f为我们定义的别名类型,然后将其赋值给另一个函数add,然后调用,本质上其实是调用了add函数!

另外,Go中我们还可以将这个定义别名为一个类型以参数进行传递,如下:

func call(a, b int, f MyFunc) (result int){
    result = f(a, b)
    return 
}

匿名函数

package main
import "fmt"

func main(){
    f := func(){
        fmt.Println("这是一个匿名函数")
    }
    f()
}

// 打印结果如下
这是一个匿名函数

观察上面代码可以得知,这是使用:=进行初始化赋值给一个变量,而后进行调用。接下来,我们进行定义一下有参数有返回值情况的匿名函数,如下:

package main
import "fmt"

func main(){
    f := func(a, b int) int {
        return a + b
    }
    
    fmt.Println(f(1, 1))
}

// 打印结果如下
2

我们还可以定义一个匿名函数的同时,让你实现自调用,如下:

package main
import "fmt"

func main(){
    
    func() {
        fmt.Println("这是一个自调用的匿名函数")
    }()
}

// 打印结果如下
这是一个自调用的匿名函数

接下来,我们再来看一下有参数有返回值的情况,如下:

package main
import "fmt"

func main(){
    result := func(a, b int) (result int){
        result = a + b
        return
    }(20, 30)
    
    fmt.Println(result)
}

// 打印结果如下
50

匿名函数还可以作为一个函数的返回值使用,如下:

package main
import "fmt"

func test() func(num int) int {
    return func(num int) (result int) {
        result = num * num
        return
    }
}

func main() {
    f := test()
    fmt.Println(f(2))
}

// 打印结果如下
4
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值