• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

go:函数

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

1. 简介

1.1 函数类型

  1. 普通带有名字的函数;

  2. 匿名函数或者 lambda 函数;

  3. 方法(Methods)

1.2 函数签名

  除了main()、init()函数外,其它所有类型的函数都可以有参数返回值。函数参数、返回值以及它们的类型被统称为函数签名

  go里面函数不允许重载,函数名需保证在包内的唯一性;

1.3 函数作为参数

  函数可以将其他函数作为它的参数,只要这个被调用函数的返回值个数、返回值类型和返回值的顺序与调用函数所需求的实参是一致的;

  示例:

package main

import "fmt"

func main()  {

    fun1(fun2())
}

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

func fun2()(a int,b int,c int)  {
    return 1,2,3
}
View Code

 1.4 函数类型

  函数也可以以申明的方式被使用,作为一个函数类型;

  函数类型可以赋值给变量,就像 add := binOp 一样,这个变量知道自己指向的函数的签名,所以给它赋一个具有不同签名的函数值是不可能的;

  函数值(functions value)之间可以相互比较:如果它们引用的是相同的函数或者都是 nil 的话,则认为它们是相同的函数;

type binOp func(int, int) int

 1.5 声明外部定义的函数

  如果需要申明一个在外部定义的函数,你只需要给出函数名与函数签名,不需要给出函数体:

func flushICache(begin, end uintptr) // implemented externally

 2. 函数参数和返回值

  go 语言的函数可以返回多个返回值,称为一组返回值;

  函数定义时,它的形参一般是有名字的,不过我们也可以定义没有形参名的函数,只有相应的形参类型,就像这样:func add ( int, int )

  没有参数的函数通常被称为 niladic 函数(niladic function),就像 main.main()

2.1 值传递和引用传递

  函数调用时默认采用值传递的方式传递参数,传递的都是变量的副本,函数中对参数副本的修改不影响参数的值;

  如果需要函数直接修改参数的值,可以传递参数的地址(即指针),这样函数就可以直接修改参数的值,传递参数地址的形式:&varName;

    传递指针赋予了函数改变外部变量的能力,还可以节省内存,被修改的变量也不用return

  传递参数地址的本质也是值传递,指针也是变量类型,有自己的地址和值,通常指针的值指向一个变量的地址。所以,按引用传递也是按值传递;

2.2 返回值命名

  尽量使用命名返回值:会使代码更清晰、更简短,同时更加容易读懂

  返回值只有数据类型,没有命名返回参数名称的时候,直接返回对应类型的值即可;

func func3()(int,int)  {
    return 2,3
}

  返回值命名了参数名称时,在对返回参数赋值后,直接return即可,不用显示return 返回参数,如果没有对返回参数进行赋值操作,则返回该参数类型的零值;

func main()  {

    i, i2 := func3()
    fmt.Println(i,i2)

    a1, a2 := func4()
    fmt.Println(a1,a2)

    a12, a22 := func5()
    fmt.Println(a12,a22)
}

func func3()(int,int)  {
    /**
        输出:2 3
     */
    return 2,3
}

func func4()(a1 int,a2 int)  {
    /**
    输出: a1:12  a2:13
     */
    a1=12
    a2=13
    return
}

func func5()(a1 int,a2 int)  {
    /**
        输出: a1:12  a2:0
     */
    a1=12
    a3:=13
    fmt.Println("temp var",a3)
    return
}

2.3 空白符_

  如果不需要某个返回值,可以将这个返回值赋值给空白符

2.4  变长参数

  类似于Java,变长参数必须作为参数列表中的最后一个,形式如下:

func func6(a int, s... int ) {

}

2.5 defer

  defer 的用法类似于 Java 的 finally,用于在函数执行完成后进行释放资源的操作;

  defer 关键字可以允许程序在 return 之后执行某个语句或者函数;

  如果一个函数内有多个 defer,则会按照 defer 的定义顺序的逆序执行;

  程序按照语句顺序执行到 defer 位置时,会先计算确定 defer 函数的参数(此处已经计算确定了参数值,后面就算再修改这个参数变量的值也不会影响 defer 函数调用时的参数值 ),然后在程序 return 后执行该函数;

  被 defer 的函数可以读取并修改有变量名的返回参数,一般配合匿名函数使用;

  示例:

package main

import "fmt"

func main() {

    deferOrder()
    defineDeferParamFuncValue()
    defineDeferParamValue()
    fmt.Println(modifyReturnParamValue())
}

func trace(s string) string {
    fmt.Println("entering:", s)
    return s
}

func un(s string) {
    fmt.Println("leaving:", s)
}
func deferOrder() {
    /**
        输出:
        in func deferOrder
        a2
        a1
     */
    defer fmt.Println("a1")
    fmt.Println("in func deferOrder")
    defer fmt.Println("a2")
}

func defineDeferParamFuncValue() {
    /**
        输出:
        entering: func defineDeferParamFuncValue
        in func defineDeferParamFuncValue
        leaving: func defineDeferParamFuncValue
     */
    // 程序执行到此处时,会先计算确定 defer 函数的参数,然后在程序 return 后执行该函数;
    defer un(trace("func defineDeferParamFuncValue"))
    fmt.Println("in func defineDeferParamFuncValue")
}

func defineDeferParamValue() {
    /**
        输出: 0
     */
    // defer 函数的参数在计算确定之后,即使参数发生变化,对已经 defer 函数的参数也没有影响
    i:=0
    defer fmt.Println("define defer param value:",i)
    i+=1
}

func modifyReturnParamValue() (x int) {
    defer func() { x++ }()
    x = 2
    return 3
}

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
go.cd自动化构建发布时间:2022-07-10
下一篇:
go的包下载失败解决方案发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap