go流程控制语句

66 阅读6分钟

 算术运算符

注意: 自增 ++ ,自减 -- 只能是 A++, A-- 且是语句 也就是说不能放到等式,函数参数等地方。

go语言没有 ++A ,--A这种语句

关系运算符用于比较两个值,并返回一个布尔值(true 或 false)

逻辑运算符

位运算符

假定 A 为60,B 为13 。 A := 0b111100

B := 0b001101

&^运算符(按位清除)

A&^ B:如果 B 的某一位是 1,则将 A 的对应位设置为 0;如果 B 的某一位是 0,则 A 的对应位保持不变。

A&^ B 结果为 48, 二进制为 110000

赋值运算符

其他运算符

Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。

var a int

fmt.Printf("变量的值是: %v\t变量的地址: %[1]p\n", &a) //变量的地址: c000016098

a = 4

fmt.Printf("变量的值是: %vp\t变量的地址: %[1]p\n", &a)

Go语言中,指针是一个变量的内存地址。就是一个存储了其他数据项地址的数据项,或者说指针是一个存储了其他变量地址的变量。

  • Go 语言中的指针与 C/C++ 中的指针类似,但是 Go 语言中的指针不能进行指针运算,也不能进行指针类型转换。
  • 指针是一种特殊的变量,它存储了一个变量的内存地址。通过指针,我们可以直接访问和修改变量的值,而不需要拷贝变量本身,这样可以提高程序的效率。指针在Go语言中有以下几个作用
  1. 传递变量的地址:指针可以作为函数参数,将变量的地址传递给函数,这样函数就可以直接修改变量的值。
  2. 动态分配内存:通过指针可以在运行时动态分配内存,这样程序就可以根据需要动态地创建和销毁变量。
  3. 访问复杂数据结构:指针可以用于访问复杂的数据结构,如链表、树等,通过指针可以方便地遍历和修改这些数据结构。
  4. 函数返回值:指针可以作为函数的返回值,这样函数就可以返回一个指向变量的指针,而不是变量本身,这样可以避免变量拷贝和内存分配的开销。

指针定义

var 指针变量名称 *指针类型

new()函数使用

开辟数据类型对应的内存空间,返回值为数据类型指针

var p *int

p = new(int) //int占用4字节,也就是开辟4字节的内存空间,给p指针变量

*p = 666

fmt.Println(p)

运算符优先级

Operator precedence

Unary operators have the highest precedence. As the ++ and -- operators form statements, not expressions, they fall outside the operator hierarchy. As a consequence, statement *p++ is the same as (*p)++.

There are five precedence levels for binary operators. Multiplication operators bind strongest, followed by addition operators, comparison operators, && (logical AND), and finally || (logical OR):

Precedence    Operator
    5             *  /  %  <<  >>  &  &^
    4             +  -  |  ^
    3             ==  !=  <  <=  >  >=
    2             &&
    1             ||

以上来自golang官网:

大概翻译

一元运算符具有最高的优先级。 因为 ++ 和 -- 运算符形成 语句,而不是表达式,它们位于 运算符层次结构之外。 因此,语句 *p++ 与 (*p)++ 相同。

二元运算符有五个优先级。 乘法运算符结合得最紧,其次是加法运算符、比较运算符、&&(逻辑与), 最后是||(逻辑或):

优先级    操作符
    5       *  /  %  <<  >>  &  &^
    4       +  -  |  ^
    3       ==  不等于  <  <=  >  >=
    2       &&
    1       ||

需要注意go和其他语言不太一样. 位移运算符 高于 加减

java运算符优先级:

从高到低排列:

  1. 后缀运算符:() [] .
  2. 一元运算符:++ -- + - ! ~
  3. 乘除模运算符:* / %
  4. 加减运算符:+ -
  5. 移位运算符:<< >> >>>
  6. 关系运算符:< <= > >= instanceof
  7. 相等运算符:== !=
  8. 按位与运算符:&
  9. 按位异或运算符:^
  10. 按位或运算符:|
  11. 逻辑与运算符:&&
  12. 逻辑或运算符:||
  13. 三元运算符:? :
  14. 赋值运算符:= += -= *= /= %= &= ^= |= <<= >>= >>>=

if分支结构语句

// 可以在 if 表达式之前添加一个执行语句"score := 65;",再根据变量值进行判断:
        if score := 65; score >= 90 {
                fmt.Println("A")
        } else if score > 75 {
                fmt.Println("B")
        } else {
                fmt.Println("C")
        }
//  fmt.Println(score)   错误:score的作用域只在if里,出了if作用域就取不到这个score的变量了

if嵌套

题目:三只小猪比体重。

a=10 b=8 c=12 求那只小猪最重

转存失败,建议直接上传图片文件

switch case

  • Go语言switch语句常规写法

switch var1 {

case value1,value2:

// do something

case value3:

// do something

default:

// do something

}

  • switch后无变量,case后必须是判断符

a := 20

switch { // switch后没有待比较变量

case a > 0: // 此时case后必须是判断表达式,为true时进入

        fmt.Println("positive")

case a < 0:

        fmt.Println("negative")

default:

        fmt.Println("zero")

}

go语言中switch不像其他语言,需要在case后加break防止 case穿透

go语言,不需要加break,是不会有case穿透的。

如果想在Go语言中实现穿透效果,使用fallthrough穿透当前case语句块。

fallthrough 只能穿透一层,意思是它让你直接执行下一个case的语句,而且不需要判断条件。

for循环

Go 语言的 For 循环有 3 种形式,只有其中的一种使用分号。

  1. for init; condition; post { }
  2. for condition { }
  3. for { }

例子

       // 正常for循环
            for i := 0; i < 3; i++ {
                    fmt.Printf("i=%d\t", i)
            }
           // 变形写法
            i := 0
            for i < 3 {
                    fmt.Printf("i=%d\t", i)
                    i = i + 1
            }
      // 死循环
         for true {
                      fmt.Println("Hello World")
         }
         // 或者直接把true也省略
            for {
                    fmt.Println("Hello World")
            }


continue

中止当前这一趟循环体的执行,直接执行“循环后操作”后,进入下一趟循环的条件判断。


for i := 0; i < 10; i++ {
        if i%2 == 0 {

                continue

        }

        fmt.Println(i)

}

break

终止当前循环的执行。


for i := 0; ; i++ {

        if i%2 == 0 {

                continue

        }

        fmt.Println(i)

        if i >= 10 {

                break

        }

} // 请问执行结果是什么?

除了break,函数的return结束函数执行,当然也能把函数中的循环打断。

goto和label

这是一个被很多语言尘封或者废弃的关键字,它会破坏结构化编程,但是确实能做到便利的无条件跳转。

goto需要配合标签label使用,label就像代码中的锚点,goto将无条件跳到那里开始向后执行代码。

for i := 0; ; i++ {

        if i%2 == 0 {

                continue

        }

        fmt.Println(i)

        if i > 10 {

                goto condition

        }

}

condition:

fmt.Println("done")

continue、break也可以指定label,方便某些循环使用。但是,建议不要这么写,弄不好就成了毛线团。

for range

for range遍历字符串

  • for range 按照字符偏移(rune类型),中文是utf-8编码,占3个字节
  • len(s)按照字节偏移(byte类型)

for i, v := range "abcd测试" {

        fmt.Printf("%d: %T, %[2]v, %[2]c\n", i, v)

}

fmt.Println("\xe6\xb5\x8b\xe8\xaf\x95")

/*

运行结果如下

0: int32, 97, a

1: int32, 98, b

2: int32, 99, c

3: int32, 100, d

4: int32, 27979, 测

7: int32, 35797, 试

测试

*/

s := "abcd测试"

for i := 0; i < len(s); i++ { //len返回字符串的字节数

        fmt.Printf("%d: %T %[2]v, %[2]c\n", i, s[i])

}

/*

运行结果如下

0: uint8 97, a

1: uint8 98, b

2: uint8 99, c

3: uint8 100, d

4: uint8 230, æ

5: uint8 181, µ

6: uint8 139, ‹

7: uint8 232, è

8: uint8 175, ¯

9: uint8 149, •

*/