常量

概述: 常量与运算符是基本概念,对于Go语言,可以使用它们进行赋值、计算和比较。Go语言支持的运算包括算术运算、比较运算和逻辑运算等。

所谓常量,就是值不能变的量,比如常用的数学常数“π”就是一个常量。大多数的编程语言会使用全大写的变量名表示常量,所以约定俗成,如果常量的名字是全大写的变量,一般不做修改。

常量的定义

常量的声明以关键字const开头,后接变量类型并进行赋值,行尾没有其他标点符号。
常量的显式声明格式如下:

1
const 常量名 常量类型 = value

注意⚠️:一个常量被声明后可以不使用,但是变量一旦声明则必须使用。

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
const a float64 = 3.1415
const b string = "Hello World"
fmt.Println(a)
}

// 3.1415

由于Go是编译型语言,定义常量时可以省略常量类型,因为编译器可以根据变量的值来推断其类型。
常量的隐式声明格式如下:

1
const 常量名 = value
1
2
3
4
5
6
7
8
9
10
11
12
package main

import "fmt"

const a = 3.1415
const b = "Hello world"

func main() {
fmt.Println(a)
}

// 3.1415

如果程序需要用到大量值相同的常量,我们可以直接定义常量组。在定义常量组时,若不提供初始值,则表示将使用上行的表达式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"

const (
a = 3.1415
b
c
d = "Hello world"
)

func main() {
fmt.Println("a:",a)
fmt.Println("b:",b)
fmt.Println("c:",c)
fmt.Println("d:",d)
}

// a: 3.1415
// b: 3.1415
// c: 3.1415
// d: Hello world

枚举通常针对一个有穷序列集而言,一个集的枚举就是列出有穷序列集的所有成员。
Go语言现阶段还没有枚举,但是我们可以使用一种特殊常量“iota”来模拟枚举。
iota在const关键字出现时被重置为0,const中每新增一行常量声明,将使iota进行一次计数,可以简单地将iota理解为const语句块中的行索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import "fmt"

const (
a = iota //0
b //沿用上一行iota,并计数 1
c = "Hello world" //iota += 1, iota = 2
d //沿用上一行"Hello world",iota += 1, iota = 3
e = iota iota += 1, iota = 4
)

func main() {
fmt.Println("a:",a)
fmt.Println("b:",b)
fmt.Println("c:",c)
fmt.Println("d:",d)
fmt.Println("e:",e)
}

// a: 0
// b: 1
// c: Hello world
// d: Hello world
// e: 4

运算符

Go数据是通过使用操作运算符来进行操作的,与数学运算符类似。操作运算符接受一个或多个参数,并生成一个新的值。

算术运算符用于Go语言的数学表达式中,它们的作用和在数学中的作用一样。

运算符 说明 示例
+ 加法:相加运算符两侧的值 a + b
- 减法:左操作数减去右操作数 a - b
* 乘法:操作符两侧的值相乘 a * b
/ 除法:左操作数除以右操作数 a / b
取模:左操作数除以右操作数的余数 a % b
++ 自增:操作数加 1 a++
自减:操作数减 1 a–
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import "fmt"

func main() {
a := 1
b := 2
fmt.Println("a+b=",a+b)
fmt.Println("a-b=",a-b)
fmt.Println("a*b=",a*b)
fmt.Println("a/b=",a/b)
fmt.Println("a%b=",a%b)

a++
fmt.Println("a++后a值为:",a)
b--
fmt.Println("b--后b值为:",b)
}


// a+b= 3
// a-b= -1
// a*b= 2
// a/b= 0
// a%b= 1
// a++后a值为: 2
// b--后b值为: 1

比较运算符,对符号两边的变量进行比较,包括大小、相等等。如果比较结果是正确,返回真(true),否则返回假(false)。

运算符 说明 示例
== 等于:比较对象是否相等 a == b
!= 不等于:比较两个对象是否不相等 a != b
> 大于:返回 a 是否大于 b a > b
< 小于:返回 a 是否小于 b a < b
>= 大于等于:返回 x 是否大于等于 y x >= y
<= 小于等于:返回 x 是否小于等于 y x <= y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import "fmt"

func main() {
a := 1
b := 2
fmt.Println("a==b",a==b)
fmt.Println("a!=b",a!=b)
fmt.Println("a>b",a>b)
fmt.Println("a<b",a<b)
fmt.Println("a>=b",a>=b)
fmt.Println("a<=b",a<=b)

}

// a==b false
// a!=b true
// a>b false
// a<b true
// a>=b false
// a<=b true

最常用的赋值运算符是等号“=”,表示把右边的结果值赋值给左边的变量。其他的赋值运算符大多都是算术运算符和赋值运算符的简写。

运算符 说明 示例 展开形式
= 将右边值赋值给左边 a=100 a=100
+= 将左边值加右边值 a+=10 a=a+10
-= 将左边值减右边值 a-=10 a=a-10
*= 将左边值乘以右边值 a*=10 a=a*10
/= 将左边值除以右边值 a/=10 a=a/10
%= 将左边值对右边值做取模 a%=10 a=a%10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

import "fmt"

func main() {
var a = 10
fmt.Println("a=",a)
a += 2
fmt.Println("a += 2 ,a=",a)
a -= 2
fmt.Println("a -= 2 ,a=",a)
a *= 2
fmt.Println("a *= 2 ,a=",a)
a /= 2
fmt.Println("a /= 2 ,a=",a)
a %= 2
fmt.Println("a %= 2 ,a=",a)
}

// a= 10
// a += 2 ,a= 12
// a -= 2 ,a= 10
// a *= 2 ,a= 20
// a /= 2 ,a= 10
// a %= 2 ,a= 0

Go定义了位运算符,应用在两个数的运算上,会对数字的二进制所有位数从低到高进行运算。

运算符 说明 示例
按位与,如果相对应位都是 1,则结果为 1,否则为 0 a & b
| 按位或,如果相对应位都是 0,则结果为 0,否则为 1 a | b
^ 按位异或,如果相对应位值相同,则结果为 0,否则为 1 a ^ b
<< 按位左移运算符,左操作数按位左移右操作数指定的位数 a << b
>> 按位右移运算符,左操作数按位右移右操作数指定的位数 a >> b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

func main() {
a := 9
b := 13
fmt.Println("a&b = ",a&b)
fmt.Println("a|b = ",a|b)
fmt.Println("a^b = ",a^b)
fmt.Println("a<<2 = ",a<<2)
fmt.Println("b>>2 = ",b>>2)
}

// a&b = 9
// a|b = 13
// a^b = 4
// a<<b = 36
// a>>b = 3

与运算: 两个都为1 才为1
或运算: 有一个为1 就为1
异或运算: 两个值不同 才为1

  • 按位与:将参与运算的两个数按二进制位展开后进行与运算,9按二进制位展开为1001,13按二进制位展开为1101,1001和1101的与运算结果为1001,即十进制9。
  • 按位或:将参与运算的两个数按二进制位展开后进行或运算,9按二进制位展开为1001,13按二进制位展开为1101,1001和1101的或运算结果为1101,即十进制13。
  • 按位异或:将参与运算的两个数按二进制位展开后进行异或运算,9按二进制位展开为1001,13按二进制位展开为1101,1001和1101的异或运算结果为0100,即十进制4。
  • 按位左移:将参与运算的数按二进制位展开后全部左移指定位数,9按二进制位展开为1001,全部左移2位后变为100100,即十进制36。从右往左推补零
  • 按位右移:将参与运算的数按二进制位展开后全部右移指定位数,13按二进制位展开为1101,全部右移2位后变为11,即十进制3。从左往右推补零

逻辑运算符在Go语言中非常重要,广泛应用在逻辑判断的地方。

运算符 说明 示例
&& 逻辑与,当且仅当两个操作数都为真,条件才为真 a && b
|| 逻辑或,两个操作数中任意一个为真,条件为真 a || b
! 逻辑非,用来反转操作数的逻辑状态。如果条件为 true,则逻辑非运算符将得到 false !a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import "fmt"

func main() {
a := true
b :=false
fmt.Println("a&&b = ",a&&b)
fmt.Println("a||b = ",a||b)
fmt.Println("!a = ",!a)
}

// a&&b = false
// a||b = true
// !a = false

需要注意的是按位取反运算符“^”,它和按位异或运算符不同,涉及的操作数只有一个,因此也可归类为单目运算符。

运算符 说明 示例
& 返回变量存储地址 &a
* 指针变量 *a
^ 按位取反(注意与按位异或区分) ^a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package main

import "fmt"

func main() {
a:=1
var p *int
p = &a
fmt.Println("变量a地址为:",p)
fmt.Println("变量a内容为:",*p)
fmt.Println("^a = ",^a)
}

// 变量a地址为: 0xc00000a0b0
// 变量a内容为: 1
// ^a = -2

正数1按二进制位展开为001,其中最左位0表示正数,取反操作对所有二进制位取反,结果为110,其中最左位1表示负数,即十进制-2。

运算符优先级

表由上至下代表优先级由高到低。(表中第一行运算符“^”代表按位取反运算符,第八行运算符“^”代表按位异或运算符。)

运算符 关联性
! 、^ 、++、– 从右到左
*(乘)、 / 、% 从左到右
+(加) 、-(减) 从左到右
<<、 >> 从左到右
< 、<=、 >、 >= 从左到右
==、 != 从左到右
&(按位与) 从左到右
^ 从左到右
| 从左到右
&& 从左到右
|| 从左到右
=、+=、-=、*=、/=、%=、>>=、<<=、&=、^=、|= 从右到左