go 流程控制及函数相关

流程控制

switch

  1. go语言中的case不仅可以基于常量进行判断,也可以基于表达式进行判断,不用写break
  2. 一分支多值: case “1”,”2”
  3. 分支表达式:case 4>r &&r>2 // 这种条件下switch后不再跟判断变量(无判断目标)
  4. fallthrough关键字,执行完一个Case后会执行下一个case,不建议使用。

goto

  1. 可以退出多层循环 在循环中goto xxx,循环外xxx: 代码
  2. 统一错误处理,在处理处均goto xxx,在进行处理处 xxx: 代码

break

  1. 跳出指定循环

outloop:

       循环1

          循环2 {

break outloop

}

函数

  1. go语言函数本身可以作为值传递
  2. 支持匿名函数和闭包
  3. 函数可以满足接口

函数的返回值(支持多返回值)

  1. 同一类型返回值

func xxx() (int,int){

        return 1,2

}

  1. 带有变量名的返回值

func xxx() (a,b int) {

        a=1

b=2   //或return a,2

return

}

同一种类型返回值和命名返回值两种形式只能二选一,混用会发生编译错误

函数变量

  1. 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

  1. 一般放在函数列表的末尾
  2. v …[]T,表示类型是[]T,即拥有多个  T元素的T类型切片
  3. T为可变参数的类型,当T为interface{}时,传入的可以是任意类型(比如fmt.Println()的实现)
  4. 获取可变参数的类型s.(type)
  5. 在多个可变参数中传递参数:可变参数变量是一个包含所有参数的切片,如果要在多个可变参数中传递参数,可以在传递时在可变参数变量中默认添加“...”,将切片中的元素进行传递,而不是传递可变参数变量本身。可变参数使用...进行传递与切片间使用append连接是同一个特性

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章