9.1Go之函数之函数声明

9.1Go之函数之函数声明

Go语言函数的特点

特点:

  • 在Go语言当中函数构成了代码执行的逻辑结构。

  • 函数的基本组成为:关键字 func、函数名、参数列表、返回值、函数体和返回语句

  • 每一个程序都包含很多的函数,函数是基本的代码块

  • Go语言是编译型语言,所以函数编写的顺序是无关紧要的

Go语言中的三种函数类型

  • 普通的带有名字的函数

  • 匿名函数或者 lambda 函数

  • 方法

普通函数声明(定义)

func 函数名(形式参数列表)(返回值列表){
   函数体
}

特点:

  • 如果有多个返回值需要书写返回值列表,如果没有返回值则可以不书写返回值列表

  • 如果形参或者多个返回值类型是相同的,不需要为每一个参数声明他的类型

实参与形参:

  • 实参通过值传递的方式进行传递,因此函数的形参是实参的拷贝,对形参进行修改不会影响实参,如果实参包括引用类型,如指针、slice(切片)、map、function、channel 等类型,实参可能会由于函数的间接引用被修改。

定义一个匿名函数

匿名函数的概念:

  • 需要时再定义函数

匿名函数的特点:

  • 没有函数名,只有函数体

  • 函数可以作为一种类型被赋值给函数类型的变量

  • 匿名函数可以以变量的方式传递

组成:

不带声明的:

  • 函数名

  • 函数声明

  • 函数体

匿名函数定义格式:

func(参数列表)(返回参数列表){
   函数体
}
匿名函数的调用--->匿名函数必须定义在函数内
在定义时调用匿名函数
package main

import (
"fmt"
)

func main() {
func (data int) {
fmt.Println("Hello", data)
}(100)
}
将匿名函数赋值给变量
package main

import (
"fmt"
)

func main() {
f := func(data string) {
fmt.Println("Hello", data)
}

f("JunkingBoy")
}

匿名函数的作用:

  • 本身就是一种值,可以方便地保存在各种容器中实现回调函数和操作封装。

匿名函数用作回调函数

示例代码:

package main

import "fmt"

func visit(list []int, f func(int)) {
/*循环取出切片的value*/
for _, v := range list {
f(v)
}
}

func main() {
/*使用匿名函数打印切片内容*/
visit([]int{7,8,9,1,2,3}, func(i int) {
fmt.Println(i)
})
}

代码分析:

  • func visit(list []int, f func(int)) {
    /*循环取出切片的value*/
    for _, v := range list {
    f(v)
    }
    }
    • 在这部分代码中,函数func(int)是一个匿名函数,由形参f来触发。在这里这个匿名函数func(int)仅仅只是一个容器,没有任何的具体实现

    • for循环将取出的切片的value放入到匿名函数中,(注意:这里不是形成形参列表,而是每取出一次v触发一次匿名函数)

  •     visit([]int{7,8,9,1,2,3}, func(i int) {
    fmt.Println(i)
    })
    • func(i int){}这里才开始写匿名函数的具体实现

这就满足了匿名函数的概念,调用时才实现

strings包下的匿名函数设计:

func TrimFunc(s string, f func(rune) bool) string {
   return TrimRightFunc(TrimLeftFunc(s, f), f)
}

匿名函数实现操作封装

示例代码:

package main

import (
"flag"
"fmt"
)

var skillParam = flag.String("skill", "", "skill to perform")

func main() {
/*解析命令行参数*/
flag.Parsed()

//利用匿名函数赋值给skill变量
var skill = map[string]func(){
"fire": func() {
fmt.Println("chicken fire")
},
"run": func() {
fmt.Println("soldier run")
},
"fly": func() {
fmt.Println("angel fly")
},
}

if f, ok := skill[*skillParam]; ok {
f()
}else {
fmt.Println("skill not found")
}
}

代码分析:

  • var skillParam = flag.String("skill", "", "skill to perform")
    • 定义了命令行参数skill,将=后的字符串传入skillParam指针变量

  • /*解析命令行参数*/
    flag.Parsed()
    • 解析命令行参数,解析完成后,skillParam 指针变量将指向命令行传入的值

  • var skill = map[string]func()
    • 定义一个字符串映射到func()map。它下面的代码是填充map

  • var skill = map[string]func(){
    "fire": func() {
    fmt.Println("chicken fire")
    },
    "run": func() {
    fmt.Println("soldier run")
    },
    "fly": func() {
    fmt.Println("angel fly")
    },
    }
    • 初始化map的键值对引用,值为匿名函数

  • if f, ok := skill[*skillParam]; ok
    • skillParam是一个 *string类型的指针变量,使用 *skillParam 获取到命令行传过来的值,并在 map 中查找对应命令行参数指定的字符串的函数。

    • 在这里要注意:f其实的真实的值是:var f func() = skill[*skillParam],ok的真实值是:var ok bool

    • if是用来进行逻辑判断的,会根据f的执行结果来调用是执行f()还是打印语句

    •  

It's a lonely road!!!
原文地址:https://www.cnblogs.com/JunkingBoy/p/15232408.html