Fork me on GitHub

Go语言入门——函数

写了快一个月的Go,已经没有什么陌生感了。

 

一行代码写完,不会在行尾本能的敲上“;”,直接Enter键换行;

定义变量把变量名放在前面,类型放在后面;

使用struct去定义自己想要的数据模型就好比定义一个Java中的model一样……

 

这些不用可以经过大脑加工思考,就想自己还在写Java一样。

 

还记得当时在看《Go实战》的时候看到变量类型后置的声明方式,我还在极力吐槽这种不人性的语法,如果我已经站在了真香的队伍里,和其他的真香同学别无二致。

感慨,人的适应能力真的强👍

作为一个Java重度爱好者,其实在每次写Go的时候都会情不自禁的把两者进行对比,在写文章的时候也会经常提到。当然了,今天主要说的还是Go的函数。

 

1、Go语言中的函数长啥样

func f(a int, b int) (ret int, err error) {
    fmt.Println("This is function")
    return
}

  

没错,这大概就是一个典型的Go风格的函数,那么它有哪些特色

  • 入参
  • 返回值

 

2、入参

2.1 参数合并声明

入参的变量也是变量后置的,这里a变量和b变量是相同类型的,所以也可以写成

a, b int

对于不同类型的参数需要分开定义。

 

2.2 不定参数

除此以外,入参还支持不定参数

比如可以这样定义

func f(args ...int) {
    for _, arg := range args {
        fmt.Println(arg)
    }
}

针对不定参数的函数,我们可以这样调用

f(1)

f(1, 2)

f(1, 2, 3)

避免了我们在函数里定义一长串变量的情况。

上面的不定参数是int类型的,那么是否支持多种类型混用的不定参数呢?

是可以的,使用...interface{}这种形式

func f(args ...interface{}) {
    for _, arg := range args {
        switch arg.(type) {
            case int:
            	fmt.Println("It is int type")
            case string:
            	fmt.Println("It is string type")
            case int64:
            	fmt.Println("It is int64 type")
        }
    }
}

 

注意,这里的i.(T)形式不是强制转换或者隐式类型转换,这是类型断言,表示判定类型的。

Go里面是没有隐式类型转换的,不仅没有,而且强制类型转换也很严格。

 

3、返回值

3.1 返回参数

不同于Java,Go函数是可以支持多返回值的,比如这里返回了ret和err两个参数。

返回值的定义方式也很灵活,可以写成

func f(a int, b int) (int, error) {
    fmt.Println("This is function")
    return
}

如果返回只有一个参数可以写成

func f(a int, b int) (ret int) {
    fmt.Println("This is function")
    return
}

或者

func f(a int, b int) int {
    fmt.Println("This is function")
    return
}

  

3.2 “_”的用法

在前面的文章,我们也顺带提过,对于函数返回的值,有些我们不关心或者不需要的话,我们不能抹掉他的位置,但是可以使用"_"来表示这个参数的存在,只是不用而已,比如这样调用上面的函数是不行的

ret := f(1, 2)	// 缺少err返回值

但是这样是OK的

ret, _ := f(1, 2)

或者这样

_, err := f(1, 2)	

  

3.3 error

error接口是Go标准库为了错误处理提供的接口。

一般在业务代码中,我们会调用某个方法后,判定方法对应的值是否为nil判定方法是否被正常执行

if err != nil {
    // 没有正常执行
} else {
    // 正常执行
}

  

3.4 panic和recover和defer

说到error,正好说说panic()和recover()两个函数

当我们遇到一些err的时候,我们可能就会直接抛出panic,这里的panic可以近似理解为Java里面的Exception,即抛出异常。

if err != nil {
    panic(err)
}

一旦抛出panic,则程序将会终止,除非遇到一种情况,即有recover的存在。

说到recover则不得不提defer

defer是Go里面的新特性,有点类型Java里面的finally,承担回收资源或者解锁这类的收尾工作,但是比finally要灵活,Go函数的defer可以放在函数的任意位置,不管函数是否正常执行,在跳出函数前都会执行defer定义的函数。

接着说recover,如果在函数抛出panic,只要在最后遇到recover也是可以恢复正常的,形式如下

defer func() {
    if ret := recover(); ret != nil {
        fmt.Println("Catch Runtime Error:)
    }
}

  

4、其他

4.1 说说func

每个函数都以func开始,来表明自己是一个函数。

那么学过Java的肯定会问,没有像public、private这样的访问修饰符吗?

没有,但是Go通过另外一种规则实现了访问范围即可见性。对于函数名使用大写字母开头,则表示可以被其他包使用,如果使用小写字母开头,则只能本包内使用。

当然,这个规则,也适用于变量的声明。

 

4.2 匿名函数

和Java等其他语言一样,Go函数也有匿名函数。

func (a, b int, s string) int {
    ...
}

可以通过直接在后面赋值的方式直接执行

func (a, b int, s string) int {
    ...
}(1, 2, "test")

这里主要从Go语言的函数构成包括关键字func,入参和返回值介绍Go函数的一些特性。当然了,Go函数还有很多灵活性就不再一一阐述了,有待你我在业务项目中慢慢实践体会了。

 

5、技术沙龙

今天去参加了一个技术沙龙,主题是数据存储与微服务架构实践方面的。

这是自己第一次除了参加公司组织的各种会议以外,自己主动报名的线下技术沙龙。

会上听到了阿里、百度的大佬分享关于过去的技术沉淀和对未来技术方向的展望,整体还是蛮有收获的。

拓宽了自己的知识面,也加深了对一些框架或者工具的理解,比如ServiceMesh。之前对于ServiceMesh的理解仅限于阅读各种文章,自己的理解也比较有限,这次通过阿里大佬的解释,更加清晰的了解了ServiceMesh以及它的优势。

最后晒一下在回答问题环节,主办方送的马克杯,好评

 

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

posted @ 2019-06-15 23:54  JackieZheng  阅读(395)  评论(0编辑  收藏  举报