流程控制
switch
- go语言中的case不仅可以基于常量进行判断,也可以基于表达式进行判断,不用写break
- 一分支多值: case “1”,”2”
- 分支表达式:case 4>r &&r>2 // 这种条件下switch后不再跟判断变量(无判断目标)
- fallthrough关键字,执行完一个Case后会执行下一个case,不建议使用。
goto
- 可以退出多层循环 在循环中goto xxx,循环外xxx: 代码
- 统一错误处理,在处理处均goto xxx,在进行处理处 xxx: 代码
break
- 跳出指定循环
outloop:
循环1
循环2 {
break outloop
}
函数
- go语言函数本身可以作为值传递
- 支持匿名函数和闭包
- 函数可以满足接口
函数的返回值(支持多返回值)
- 同一类型返回值
func xxx() (int,int){
return 1,2
}
- 带有变量名的返回值
func xxx() (a,b int) {
a=1
b=2 //或return a,2
return
}
同一种类型返回值和命名返回值两种形式只能二选一,混用会发生编译错误
函数变量
- go语言中函数也是一种类型func(),可以和其他类型一样被保存在变量中。例如:
func fire(){
}
var f func()
f=fire
f()
匿名函数
定义
func(参数列表) (返回参数列表) {
函数体
}
在定义时调用
func(参数列表) (返回参数列表) {
函数体
}(实参列表)
赋值给变量
f := func(参数列表) (返回参数列表) {
函数体
}
f(实参列表)//通过变量调用
作回调函数
func visit(list []int, f func(int)) {
for _, value := range list {
f(value)
}
}
func main() {
// 使用匿名函数打印切片内容
visit([]int{1, 2, 3, 4, 5}, func(v int) {
fmt.Println(v)
})
}
实现操作封装
func main() {
flag.Parse()
// 将匿名函数作为map的键值,输入不同的key,执行不同的键值
var skill = map[string]func(){
"fire": func() {
fmt.Println("chicken fire")
},
"run": func() {
fmt.Println("soldier run")
},
"fly": func() {
fmt.Println("angel fly")
},
}
// *skillParam获取命令行传来的值,并在map中查找对应命令行参数指定的字符串的函数
if f, ok := skill[*skillParam]; ok {
f()
} else {
fmt.Println("skill not found")
}
}
函数作为接口调用
/* 函数实现接口 */
// 函数定义为类型
type FuncCaller func(interface{}) //将func(interface{})定义为FuncCaller类型
// 实现Invoker的Call
func (f FuncCaller) Call(p interface{}) { //FuncCaller的Call方法实现Invoker的Call方法
// 调用f()函数本体
f(p) // FuncCaller的Call方法被调用还需函数本体,需要函数本身进行逻辑处理
}
// FuncCaller无需被实例化,只需要将函数转化为FuncCall即可
var in2 Invoker //声明接口变量
// 将匿名函数转为FuncCall类型,再赋值给接口
in2 = FuncCaller(func(v interface{}) {
fmt.Println("fron function", v)
})
// 使用接口调用 FuncCaller.Call,内部会调用函数本体
in2.Call("hellp")
闭包
类似c++中的lambda表达式,函数是编译时静态的概念,闭包是运行时动态的概念
c++与c#为闭包创建了一个类,被捕获的变量在编译时放到类的成员中,闭包在访问被捕获的变量时,实际上访问的是闭包隐藏类的成员。
可变参数
v…T
- 一般放在函数列表的末尾
- v …[]T,表示类型是[]T,即拥有多个 T元素的T类型切片
- T为可变参数的类型,当T为interface{}时,传入的可以是任意类型(比如fmt.Println()的实现)
- 获取可变参数的类型s.(type)
- 在多个可变参数中传递参数:可变参数变量是一个包含所有参数的切片,如果要在多个可变参数中传递参数,可以在传递时在可变参数变量中默认添加“...”,将切片中的元素进行传递,而不是传递可变参数变量本身。可变参数使用...进行传递与切片间使用append连接是同一个特性