Go语言函数

函数的定义和调用

package main

import "fmt"

// 函数的定义
// func 函数名(参数)(返回值){
//  函数体
// }
// 函数定义
func add(a int, b int) (ret int) {
    return a + b
}

func main() {
        // 函数的调用
    result := add(1, 1)
    fmt.Println(result) //2
}
  • 函数名:由字母、数字、下划线组成。但函数名的第一个字母不能是数字。在同一个包内,函数名也不能重复。
  • 参数:参数由参数变量和参数变量类型组成,多个参数之间使用逗号分隔。
  • 返回值:返回值由返回值变量和其变量类型组成,也可以只写返回值类型,多个返回值必须使用()分隔,并用逗号分隔。
  • 函数体:实现指定功能的代码块。

参数类型简写

函数的参数中如果相邻变量的类型相同,则可以省略

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

可变参数

可变参数是指函数的参数数量不固定。Go语言中的可变参数通过在参数名后加...来标识。需要注意的是,可变参数通常要作为函数的最后一个参数。

package main

import "fmt"

// 可变参数
func add(a ...int) (ret int) {
        // a是一个切片
    sum := 0
    for _, v := range a {
        sum += v
    }
    return sum
}

func main() {
    fmt.Println(add(1, 1))       //2
    fmt.Println(add(1, 1, 1))    //3
    fmt.Println(add(1, 1, 1, 1)) //4
}

返回值

Go语言中支持多返回值,函数如果有多个返回值必须使用()将所有返回值包裹起来。

package main

import "fmt"

// 多返回值
func add(a int, b string) (int, bool) {
    return 1, true
}

func main() {
    n, flag := add(1, "11")
    fmt.Println(n, flag)
}

返回值的命名

函数定义时,可以给函数返回值命名,并在函数体中直接使用这些变量

package main

import "fmt"

// 多返回值 返回值命名
func add(a int, b string) (num int, flag bool) {
    num = 123
    flag = false
    return
}

func main() {
    num, flag := add(1, "11")
    fmt.Println(num, flag)  //123,false
}

函数进阶

变量作用域

全局变量

全局变量是定义在函数外部的变量,它在程序整个运行周期内有效。在函数中可以访问到全局变量。

package main

import "fmt"

// 定义全局变量
var name = "jack"

func showName() {
    fmt.Println(name)
}

func main() {
    showName() // jack
}

局部变量

函数内定义的变量无法在函数外使用。

package main

import "fmt"

func showName() {
        // 只有函数内部才能使用这种定义变量的方法
    name := "jack"
    fmt.Println(name)
}

func main() {
    showName() // jack
    // 报错 不能再函数外使用函数内定义的变量
    // fmt.Println(name)
}

语句块中的局部变量

package main

import "fmt"

func showName() {
    name := "jack"
    flag := true
    if flag {
        age := 12
        fmt.Println(age)  //12
        fmt.Println(name) //jack
    }
    // 报错不能再函数外使用函数内定义的变量
    // fmt.Println(age)
    fmt.Println(name) //jack
}

func main() {
    showName() // jack
    // 报错 不能再函数外使用函数内定义的变量
    // fmt.Println(name)
}

函数类型和变量

定义函数类型

使用type关键字来定义一个函数类型。

package main

import "fmt"

// 定义函数类型
type calculation func(int, int) int

func add(x, y int) int {
    return x + y
}

func main() {
    // 定义函数类型变量
    var c calculation
    c = add
    result := c(1, 2)
    fmt.Println(result)  //3
}

函数变量类型

package main

import "fmt"

// 定义函数类型
type calculation func(int, int) int

func add(x, y int) int {
    return x + y
}

func main() {
    // 定义函数类型变量
    var c calculation
    c = add
    result := c(1, 2)
    fmt.Println(result)  //3
    fmt.Printf("%T\n",c) //main.calculation
}

高阶函数

函数作为参数

package main

import "fmt"

func add(x, y int) int {
    return x + y
}

func calc(x, y int, op func(int, int) int) int {
    return op(x, y)
}

func main() {
    fn := calc(1, 2, add)
    fmt.Println(fn) //3
}

函数作为返回值

package main

import "fmt"

func add(x, y int) int {
    return x + y
}
func sub(x, y int) int {
    return x - y
}
func do(s string) (func(int, int) int, error) {
    switch s {
    case "+":
        return add, nil
    case "-":
        return sub, nil
    default:
        return nil, nil
    }
}

func main() {
    fn, error := do("+")
    fmt.Println(fn(1, 2)) //3
    fmt.Println(error)    //<nil>
    fn2, error2 := do("-")
    fmt.Println(fn2(1, 2)) //-1
    fmt.Println(error2) // <nil>
}

匿名函数和闭包

匿名函数

在Go语言中,函数内部只能定义匿名函数

package main

import "fmt"

func main() {
    //  func(参数)(返回值){
    //     函数体
    // }
    add := func(x, y int) int {
        return x + y
    }
    fmt.Println(add(1, 1)) //2
}

闭包

闭包指的是一个函数和与其相关的引用环境组合而成的实体。

package main

import "fmt"

// 闭包
func adder() func(int) int {
    var x int
    return func(y int) int {
        x += y
        return x
    }
}

func main() {
    f := adder()
    fmt.Println(f(10))  //10
    fmt.Println(f(20))  //30
    fmt.Println(f(30))  //60
}

defer函数

Go语言中的defer语句会将其后面跟随的语句进行延时处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行。

package main

import "fmt"

func main() {
    fmt.Println("start")
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
    fmt.Println("end")
    // start
    // end
    // 3
    // 2
    // 1
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容

  • 1. 概述 函数是将实现单一或者相关联功能的代码组织起来,内部实现具有封闭性的代码集合,函数可以提高应用程序的模块...
    楚江云阅读 858评论 0 1
  • 函数 Go语言函数格式func 函数名称(形参列表)(返回值列表){函数语句} Go语言函数的类型没有返回值没有形...
    喝酸奶要舔盖__阅读 394评论 0 0
  • 函数 Go语言和C语言一样也有函数的概念, Go语言中函数除了定义格式和不用声明以外,其它方面几乎和C语言一模一样...
    极客江南阅读 820评论 3 6
  • 参考博客:http://c.biancheng.net/view/52.html 关键点 希望通过下面的关键点,可...
    码二哥阅读 554评论 0 5
  • broker是消息队列的核心组建,承载了消息接收,存储和转发的职责. 因此, broker需要具备各种基本功能和高...
    _呆瓜_阅读 1,916评论 1 1