Go 编程基础 控制语句 05

指针

Go虽然保留了指针,但与其他编程语言不通的是,在Go当中不支持指针运算以及->运算符,而直接采用.选择符来操作指针目标对象成员

  • 操作符 & 取变量地址,使用*通过指针间接访问目标对象
  • 默认值为nul而非NULL
func main()  {
    a := 1
    //变量b就是变量a的内存地址
    var p *int = &a
    fmt.Println(p)
    //通过内存地址 取出变量a的值
    fmt.Println(*p)
}
b

递增递减语句

在Go当中,++与--是作为语句而并不是作为表达式

func main()  {
    a := 1
    // 在go中 ++ -- 不能作为表达式,也就是不能放在等号右边,只能作为单独的一行语句
    a++
    a--
    //var b = a++
    var b = a
    fmt.Println(b)
}
1

判断语句if

  • 条件表达式没有括号
  • 支持一个初始化表达式(可以是并行方式)
  • 左大括号必须和条件语句或else在同一行
  • 支持单行模式
  • 初始化语句中的变量为block级别,同时隐藏外部同名变量
  • 1.0,3版本中的编译器的BUG

初始化语句中的变量为block级别,同时隐藏外部同名变量

func main() {
    // 声明变量a
    a := 10
    // if条件中声明a,这个a,只能在if语句中使用,如果有同名变量会暂时隐藏外部变量
    // { 括号也必须在if同一行
    if a, b := 1, 2; a > 0 {
        //1
        fmt.Println(a)
        fmt.Println(b)
    }
    // 10
    fmt.Println(a)
    // 因为b变量是在if语句中声明的,所以不能再外部使用,会报 undefined: b
    //fmt.Println(b)
}

循环语句for

  • Go只有for一个循环语句关键字,但是支持3中形式
  • 初始化和步进表达式可以使多个值
  • 条件语句每次循环都会被重新检查,因此不建议在条件语句中使用函数,尽量提前计算好条件并以便利或常量代替
  • 左大括号必须和条件语句在同一行

go for循环方式1

a := 1
    for {
        a++
        if a > 3 {
            break
        }
        fmt.Println(a)
    }
    fmt.Println("over")

go for循环方式2

b := 1
for b <= 3 {
    b++
    fmt.Println(b)
}

go for循环方式3

for i := 0; i < 3; i++ {
        fmt.Println(i)
    }

尽量不要在for循环中计算条件

func main() {
    var str = "hello"
    //这里不建议写成 i < len(str),因为每一次循环,都会走一次len函数
    var l = len(str)
    for i := 0; i < l; i++ {
        fmt.Println(i)
    }
}
0
1
2
3
4

switch 语句

  • 可以使用任何类型或表达式作为条件语句
  • 不需要写break,一旦条件符合自动终止
  • 入希望继续执行下一个case,需使用fallthrought语句
  • 支持一个初始化表达式(可以是并行方式),右侧需跟分号
  • 左大括号必须和条件语句在同一行

switch 方式1

在go中不用写break,当匹配到,,就会跳出整个switch

var a = 1
switch a {
case 0:
    fmt.Println("a=0")
case 1:
    fmt.Println("a=1")
default:
    fmt.Println("a=default")
}
a=1

switch 方式2 case 是条件表达式

func main() {
    var a = 1
    switch {
    case a >= 0:
        fmt.Println("a>=0")
        //因为这里a同样也是大于等于1的,我们这里用了 fallthrough go就会继续往下匹配
        fallthrough
    case a >= 1:
        fmt.Println("a>=1")
    default:
        fmt.Println("a=default")
    }
}
a>=0
a>=1

switch 方式3 初始化表达式

switch a := 1; {
    case a >= 0:
        fmt.Println("a>=0")
        //因为这里a同样也是大于等于1的,我们这里用了 fallthrough go就会继续往下匹配
        fallthrough
    case a >= 1:
        fmt.Println("a>=1")
    default:
        fmt.Println("a=default")
    }
    //这时候 undefined: a 说明在switch中初始化的变量,作用域也只在switch中
    //fmt.Println(a)

跳转语句 goto,break,continue

break

LABEL1:
    for {
        for i := 1; i < 10; i++ {
            if i > 3 {
                fmt.Println(i)
                break LABEL1
            }
        }
    }
    fmt.Println("OK")
}
4
OK
直接break

如果我这里直接break的话,那么只能break到内层的有限循环同级,这样,其实外层的无限循环还是会走,这就相当于一个无限循环

break到LABEL1

如果我是break到LABEL1,那就相当于我break到了最外层的for循环,这时候,就不再试一个无限循环了,这时候就可以跳出N层循环了

goto

func main() {
    //如果你把LABEL1放在循环前,那么goto还是会走下面的无限循环
    //LABEL1:
    for {
        for i := 1; i < 10; i++ {
            if i > 3 {
                fmt.Println(i)
                goto LABEL1
            }
        }
    }
    //所以,建议把LABEL1放在循环后面,这样goto就可以跳出循环了
LABEL1:
    fmt.Println("OK")
}
4
OK

continue

不要执行剩下的循环体,执行下一次的循环

错误的continue
func main() {
LABEL1:
    for {
        for i := 1; i < 10; i++ {
            if i > 3 {
                fmt.Println(i)
                //再这里continue到LABEL1,其实还是会走无限循环
                continue LABEL1
            }
        }
    }
    fmt.Println("OK")
}

其实最好的结构应该是有限循环套无限循环,无限循环中continue出去

func main() {
    LABEL1:
    for i := 1; i < 10; i++ {
        for {
            continue LABEL1
            fmt.Println("由于我前面continue了,你是看不到我的")
        }
    }
    fmt.Println("OK")
}
这样为什么不会输出ok
for i := 1; i < 10; i++ {
        for {
            continue
            fmt.Println("由于我前面continue了,你是看不到我的")
        }
    }
    fmt.Println("OK")