go控制流和一些特殊语句

来源:互联网 发布:人工智能无法替代的 编辑:程序博客网 时间:2024/06/05 04:43

send和receive语句

send、receive操作是针对channel的
send : ch <- a
receive: a := <- ch

++--语句

在go中++--是一个赋值语句,而不是一个表达式因此不能像C/C++那样编写如下代码:
a = b++
同时在go中只有后置,没有前置写法。

a++a--

if语句

ifif是编程语言中最简单的条件分支判断语句,几乎所有语言都有,所以就不介绍功能,主要介绍下写法
if语句中的条件表达式不需要加上括号

if a > 0 {    fmt.Println("a > 0")} else {    fmt.Println("a <= 0")}

if的语句中可以在判断语句中声明变量,这个变量只在if语句作用域内部有效

if a := calc(); a < 0 {    fmt.Println("result:", a)}

switch语句

switch语句中首先执行switch后面的表达式,然后执行case后面的表达式,并且是从上到下,从左到右执行,一旦有一个满足,则不再继续执行后面的操作。
switch后面不跟表达式则默认为true
case后面可以跟很多个表达式,其中一个满足则执行该case下的语句
默认情况下case下的语句执行之后会跳出switch,如果需要继续执行,使用fallthrough关键字,即使是default也可以fallthrough
if一样可以在switch表达式中声明变量
switch可以最多有一个default,当没有case条件满足的情况下执行default

switch tag {    case 0, 1, 2, 3: s1()    case 4, 5, 6, 7: s2()}switch {    case x < y : s1()    case x > y : s2()    case x = y : s3()}switch x := f(); {  // default is true    case x < 0: return -x    default: return x}

switch出了支持上述普通的表达式判断以外,还支持类型switch,这种情况下不能使用fallthrough
type有可能是nil(当变量是一个nil interface的时候)

switch i := x.(type) {case nil:    print("x is nil)case int:    print("x is int")case bool, string:    print("x is bool or string")default:    print("x is a don't know type")}

for语句

for语句有三种形式:

  • 无限循环
for {    dosomething()}
  • 类似C/C++的while形式
for a < b {    dosomething()}
  • 标准的for形式
for i := 0; i < 10; i++ {    dosomething()}

对于数组、slice、string、map、channel可以是用for range的形式,具体情况如下:

  • slice、array,返回一个index和index对应的element。
for index, value := range a {}
  • string,返回一个index和一个rune,index以byte计数,是rune在string的起始byte的index。一个rune占几个byte取决于该unicode的长度
b := "中文"for index, unicode := range a {    fmt.Println(index, string(unicode))}//输出//0 中//3 文
  • map,返回key和value
for key, value := range amap {}
  • channel,一个双向或者是接收channel,当没有数据的时候会阻塞,知道收到数据为止,channel是nil会永久阻塞,当channel关闭,循环退出
for k := range ch {}

go语句

go语句创建一个goroutine并在该goroutine中执行函数,可以是一个匿名函数

go log(i)go func(i int) {    log(i)}(1)

select语句

select语句主要用于对channel的选择,可以是接收或者发送,当操作成功的时候的时候选择对应的case,如果有多个case成功,随机选择其中一个执行。

var a []intvar c, c1, c2, c3, c4 chan intvar i1, i2 intselect {case i1 = <-c1:    print("received ", i1, " from c1\n")case c2 <- i2:    print("sent ", i2, " to c2\n")case i3, ok := (<-c3):  // same as: i3, ok := <-c3    if ok {        print("received ", i3, " from c3\n")    } else {        print("c3 is closed\n")    }case a[f()] = <-c4:    // same as:    // case t := <-c4    //  a[f()] = tdefault:    print("no communication\n")}for {  // send random sequence of bits to c    select {    case c <- 0:  // note: no statement, no fallthrough, no folding of cases    case c <- 1:    }}select {}  // block forever

return语句

return结束一个函数,并且可以返回一个或者多个返回值

func noResult() {    return}func twoResult() (int, bool) {    return 1, true}func towResultWithVariabl() (a int, b bool) {    a = 1    b = true    return   //same as return a, b}

break

break用于跳出最内层的for switch select语句,也可以通过使用label来跳出指定的label标记的for switch select

OUTER_LOOP:for i := 0; i < 10; i++ {    for j := 0; j < 10; j++ {        switch a[i][j] {            case nil : break   //跳出本次switch,same as no break.            case item: break OUTER_LOOP   //直接跳出最外层循环        }    }}

continue

continue用于直接开始最内层循环的下一个迭代,也可以通过label来继续label标记的for loop。

RowLoop:    for y, row := range rows {        for x, data := range row {            if data == endOfRow {                continue RowLoop            }            row[x] = data + bias(x, y)        }    }

goto

和C/C++中的goto一样,跳转到指定的label处,goto不能跳过作用域中的变量声明,也不能跳转到不同的作用域中去

goto Lv := 3L: dosomething() //错误,跳过了v的声明if n%2 == 1 {    goto L1}for n > 0 {    fn()    n--L1     fn()    n--}//错误,从一个作用域跳转到另外一个作用域

defer

defer是一个函数的执行推迟到其调用defer的函数的return之前执行。
多个defer的执行顺序是和编写顺序逆序执行的

func dosomething() int {}func do() int {    lock(l)    defer unlock(l) //unlock will execute after dosomething    ...    return dosomething()}for i := 0; i < 10; i++ {    defer fmt.Println(i)}这样将输出9到0

recover and panic

panic将直接从调用panic的当前函数中返回,并且如果panic没有被recover,那么程序将直接crash。
可以通过defer和recover来从panic错误中恢复。

func protect(g func()) {    defer func() {        log.Println("done")  // Println executes normally even if there is a panic        //catch panic 并且从panic中恢复,以保证程序不会crash,而是可以继续执行。        if x := recover(); x != nil {            log.Printf("run time panic: %v", x)        }    }()    log.Println("start")    g()}
0 0
原创粉丝点击