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()还是打印语句
- 
 
- 
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号