算术运算符
注意: 自增 ++ ,自减 -- 只能是 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语言中有以下几个作用
- 传递变量的地址:指针可以作为函数参数,将变量的地址传递给函数,这样函数就可以直接修改变量的值。
- 动态分配内存:通过指针可以在运行时动态分配内存,这样程序就可以根据需要动态地创建和销毁变量。
- 访问复杂数据结构:指针可以用于访问复杂的数据结构,如链表、树等,通过指针可以方便地遍历和修改这些数据结构。
- 函数返回值:指针可以作为函数的返回值,这样函数就可以返回一个指向变量的指针,而不是变量本身,这样可以避免变量拷贝和内存分配的开销。
指针定义
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运算符优先级:
从高到低排列:
- 后缀运算符:
() [] . - 一元运算符:
++ -- + - ! ~ - 乘除模运算符:
* / % - 加减运算符:
+ - - 移位运算符:
<< >> >>> - 关系运算符:
< <= > >= instanceof - 相等运算符:
== != - 按位与运算符:
& - 按位异或运算符:
^ - 按位或运算符:
| - 逻辑与运算符:
&& - 逻辑或运算符:
|| - 三元运算符:
? : - 赋值运算符:
= += -= *= /= %= &= ^= |= <<= >>= >>>=
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 种形式,只有其中的一种使用分号。
- for init; condition; post { }
- for condition { }
- 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,
*/