Go语言入门——函数

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

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

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

使用struct去定义本身想要的数据模型就比如定义一个Java中的model同样……函数

这些不用能够通过大脑加工思考,就想本身还在写Java同样。微服务

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

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

做为一个Java重度爱好者,其实在每次写Go的时候都会不由自主的把二者进行对比,在写文章的时候也会常常提到。固然了,今天主要说的仍是Go的函数。spa

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

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

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

  • 入参
  • 返回值

二、入参

参数合并声明

入参的变量也是变量后置的,这里a变量和b变量是相同类型的,因此也能够写成cdn

a, b int
复制代码

对于不一样类型的参数须要分开定义。

不定参数

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

好比能够这样定义

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里面是没有隐式类型转换的,不只没有,并且强制类型转换也很严格。

三、返回值

返回参数

不一样于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
}
复制代码

“_”的用法

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

ret := f(1, 2)	// 缺乏err返回值
复制代码

可是这样是OK的

ret, _ := f(1, 2)	
复制代码

或者这样

_, err := f(1, 2)	
复制代码

error

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

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

if err != nil {
    // 没有正常执行
} else {
    // 正常执行
}
复制代码

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:)
    }
}
复制代码

四、其余

说说func

每一个函数都以func开始,来代表本身是一个函数。

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

没有,可是Go经过另一种规则实现了访问范围便可见性。对于函数名使用大写字母开头,则表示能够被其余包使用,若是使用小写字母开头,则只能本包内使用。

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

匿名函数

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

func (a, b int, s string) int {
    ...
}
复制代码

能够经过直接在后面赋值的方式直接执行

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

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

五、技术沙龙

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

这是本身第一次除了参加公司组织的各类会议之外,本身主动报名的线下技术沙龙。

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

拓宽了本身的知识面,也加深了对一些框架或者工具的理解,好比ServiceMesh。以前对于ServiceMesh的理解仅限于阅读各类文章,本身的理解也比较有限,此次经过阿里大佬的解释,更加清晰的了解了ServiceMesh以及它的优点。

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

我的公众号:JackieZheng 我会将我最新的文章推送给您,并和您一块儿分享我平常阅读过的优质文章

相关文章
相关标签/搜索