Go 语言变量、常量、运算符)
- 一、Go 变量
- 1.1 变量命名规则
- 说明
- 合法/非法示例
- 1.2 变量声明四大方式
- 方式1:标准声明(`var` + 变量名 + 类型)
- 语法
- 说明
- 零值规则(重点)
- 示例
- 运行结果
- 踩坑
- 方式2:声明并初始化(`var` + 变量名 + 类型 + 值)
- 语法
- 示例
- 方式3:类型推断(省略类型,编译器自动识别)
- 语法
- 说明
- 示例
- 方式4:短变量声明(`:=`,最常用)
- 语法
- 说明
- 示例
- 踩坑(高频错误)
- 1.3 多变量声明
- 1. 同行声明多个同类型变量
- 2. 同行声明多个不同类型变量(类型推断)
- 3. 因式分解写法(推荐全局变量)
- 语法
- 示例
- 4. 短变量多变量声明(函数内)
- 1.4 变量作用域
- 示例
- 1.5 空白标识符 `_`
- 说明
- 语法
- 示例
- 踩坑
- 1.6 值类型 & 引用类型
- 1. 值类型
- 示例
- 2. 引用类型
- 二、Go 常量
- 2.1 常量基础语法
- 说明
- 基础语法
- 示例
- 踩坑
- 2.2 多常量声明
- 1. 同行多常量
- 2. 因式分解批量常量(常用,枚举场景)
- 2.3 常量与内置函数
- 示例
- 2.4 特殊常量:iota(枚举计数器)
- 核心规则
- 用法1:基础自增
- 用法2:穿插自定义值,打断自增
- 用法3:位运算结合 iota(经典场景)
- 踩坑
- 三、Go 运算符
- 3.1 算术运算符
- 完整示例
- 高频踩坑
- 3.2 关系运算符(比较运算符)
- 示例
- 踩坑
- 3.3 逻辑运算符
- 示例
- 3.4 位运算符
- 示例
- 3.5 赋值运算符
- 示例
- 3.6 其他运算符(地址 & 指针)
- 示例
- 3.7 运算符优先级
- 示例(括号改变优先级)
一、Go 变量
变量用于存储数据,可读写、运行过程中值可修改。Go 是静态强类型语言,变量必须先声明再使用。
1.1 变量命名规则
说明
- 由字母、数字、下划线
_组成; - 首字符不能是数字;
- 不能使用 Go 关键字作为变量名;
- 区分大小写;
- 见名知意,推荐驼峰命名。
合法/非法示例
- 合法:
name、_age、userID、num123 - 非法:
123abc(数字开头)、a+b(含特殊符号)、case(关键字)
1.2 变量声明四大方式
方式1:标准声明(var+ 变量名 + 类型)
语法
var变量名 数据类型说明
只声明、不初始化,变量会自动赋予零值。
零值规则(重点)
- 数值类型(int/float):
0 - 布尔类型:
false - 字符串:
""(空字符串) - 指针、切片、map、channel、函数、error:
nil
示例
packagemainimport"fmt"funcmain(){varaintvarbfloat64varcboolvardstringfmt.Printf("a=%d, b=%f, c=%t, d=%q\n",a,b,c,d)}运行结果
a=0, b=0.000000, c=false, d=""踩坑
只声明不赋值的局部变量必须使用,否则编译报错declared but not used;全局变量允许声明不使用。
方式2:声明并初始化(var+ 变量名 + 类型 + 值)
语法
var变量名 类型=值示例
packagemainimport"fmt"funcmain(){varnamestring="张三"varageint=20fmt.Println(name,age)}方式3:类型推断(省略类型,编译器自动识别)
语法
var变量名=值说明
根据右侧值自动推导变量类型,日常使用频率很高。
示例
packagemainimport"fmt"funcmain(){varstr="Go语言"varnum=100fmt.Println(str,num)}方式4:短变量声明(:=,最常用)
语法
变量名:=值说明
- 等价于
var 变量名 类型 = 值; - 只能在函数内部使用,不能声明全局变量;
- 必须同时声明+赋值,不能只声明不赋值。
示例
packagemainimport"fmt"funcmain(){msg:="短变量声明"fmt.Println(msg)}踩坑(高频错误)
同一作用域不能重复用
:=声明同名变量funcmain(){a:=10a:=20// 报错:no new variables on left side of :=}修正:直接赋值
a = 20。:=不能用于全局变量msg:="全局变量"// 语法报错修正:全局变量使用
var声明。
1.3 多变量声明
1. 同行声明多个同类型变量
varv1,v2,v3 类型varv1,v2,v3 类型=值1,值2,值3示例:
vara,bint=1,2fmt.Println(a,b)2. 同行声明多个不同类型变量(类型推断)
varv1,v2=值1,值2示例:
varname,age="李四",22fmt.Println(name,age)3. 因式分解写法(推荐全局变量)
批量声明多个不同类型全局变量,代码整洁。
语法
var(变量1类型=值1变量2类型=值2变量3=值3)示例
packagemainimport"fmt"// 全局变量组var(idint=1addrstring="北京"flag=true)funcmain(){fmt.Println(id,addr,flag)}4. 短变量多变量声明(函数内)
v1,v2:=值1,值2示例:
funcmain(){x,y:=10,"test"fmt.Println(x,y)}1.4 变量作用域
- 局部变量:函数/代码块内声明,仅当前代码块有效,函数执行完毕自动销毁。
- 全局变量:函数外声明,整个包内有效;首字母大写可跨包访问。
- 变量重名:局部变量和全局变量可以同名,局部变量优先(就近原则)。
示例
packagemainimport"fmt"// 全局变量varnumint=100funcmain(){// 局部变量,覆盖全局varnumint=200fmt.Println(num)// 输出 200}1.5 空白标识符_
说明
_是只写变量,用于丢弃不需要的返回值,解决 Go 变量必须被使用的规则。
语法
_,变量=返回值1,返回值2示例
packagemainimport"fmt"// 函数返回两个值funccalc()(int,int){return10,20}funcmain(){// 丢弃第一个返回值,只接收第二个_,b:=calc()fmt.Println(b)// 20}踩坑
不能读取_的值,fmt.Println(_)直接编译报错。
1.6 值类型 & 引用类型
1. 值类型
- 包含:
int、float、bool、string、数组 - 特点:赋值时完整拷贝数据,新旧变量互不影响;变量存储在栈内存。
示例
a:=10b:=a b=20fmt.Println(a)// 10,a 不受影响2. 引用类型
- 包含:
切片、map、指针、channel、函数 - 特点:赋值时只拷贝内存地址,多个变量指向同一份数据;修改一个,全部受影响。
二、Go 常量
常量是程序运行期间值固定不可修改的量,使用const声明。
2.1 常量基础语法
说明
- 常量只能修饰:布尔、数值、字符串类型;
- 声明时必须赋值,无零值概念;
- 不能使用
:=声明常量。
基础语法
// 显式指定类型const常量名 类型=值// 类型推断(省略类型,推荐)const常量名=值示例
packagemainimport"fmt"funcmain(){constPIfloat64=3.14159constNAME="Go学习"fmt.Println(PI,NAME)}踩坑
常量声明后禁止修改,如下代码直接编译报错:
consta=10a=20// 报错:cannot assign to a2.2 多常量声明
1. 同行多常量
constc1,c2=值1,值22. 因式分解批量常量(常用,枚举场景)
const(常量1=值1常量2=值2常量3=值3)示例(简单枚举):
const(UNKNOWN=0MALE=1FEMALE=2)2.3 常量与内置函数
常量表达式中可以使用Go 内置函数(len、cap、unsafe.Sizeof),普通自定义函数不支持。
示例
packagemainimport("fmt""unsafe")const(str="hello"l=len(str)s=unsafe.Sizeof(str))funcmain(){fmt.Println(str,l,s)}2.4 特殊常量:iota(枚举计数器)
核心规则
iota是常量组专用计数器;const关键字出现时,iota重置为0;- 常量组内每新增一行,
iota自动 +1; - 上一行常量无赋值时,默认继承上一行表达式。
用法1:基础自增
packagemainimport"fmt"const(a=iota// 0b// 1(继承 a = iota)c// 2)funcmain(){fmt.Println(a,b,c)// 0 1 2}用法2:穿插自定义值,打断自增
const(a=iota// 0b// 1d="ha"// 自定义值,iota+1 → 2e// "ha",iota+1 → 3f=100// 自定义值,iota+1 → 4g// 100,iota+1 → 5h=iota// 5)用法3:位运算结合 iota(经典场景)
packagemainimport"fmt"const(i=1<<iota// 1 << 0 = 1j=3<<iota// 3 << 1 = 6k// 3 << 2 = 12l// 3 << 3 = 24)funcmain(){fmt.Println(i,j,k,l)// 1 6 12 24}踩坑
iota仅在const常量组内生效,单独使用无效;- 普通变量不能使用
iota。
三、Go 运算符
运算符用于数据运算、逻辑判断,分为:算术、关系、逻辑、位、赋值、其他运算符,同时包含优先级规则。
3.1 算术运算符
适用于数值类型,共 7 个。
| 运算符 | 作用 | 示例(A=10,B=20) |
|---|---|---|
+ | 相加 | A+B = 30 |
- | 相减 | A-B = -10 |
* | 相乘 | A*B = 200 |
/ | 整除 | B/A = 2 |
% | 取余 | B%A = 0 |
++ | 自增 | A++ → 11 |
-- | 自减 | A-- → 9 |
完整示例
packagemainimport"fmt"funcmain(){vara=21varb=10fmt.Println(a+b)fmt.Println(a-b)fmt.Println(a*b)fmt.Println(a/b)fmt.Println(a%b)a++fmt.Println(a)a--fmt.Println(a)}高频踩坑
- 整数相除结果为整数,小数部分直接舍弃:
5 / 2 = 2; - 自增/自减只能单独使用,不能参与赋值运算:
a:=10b:=a++// 编译报错,Go 不支持 - 取余
%不能用于浮点类型。
3.2 关系运算符(比较运算符)
返回结果为bool类型(true/false),常用于if/for判断。
| 运算符 | 作用 |
|---|---|
== | 相等 |
!= | 不相等 |
> | 大于 |
< | 小于 |
>= | 大于等于 |
<= | 小于等于 |
示例
packagemainimport"fmt"funcmain(){a:=21b:=10ifa==b{fmt.Println("相等")}else{fmt.Println("不相等")}fmt.Println(a>b)}踩坑
判断相等是==,不要写成赋值=。
3.3 逻辑运算符
多用于多条件组合判断,操作数和结果均为布尔值。
| 运算符 | 名称 | 规则 |
|---|---|---|
&& | 逻辑与 | 两边都为 true,结果才为 true(短路:左边 false 直接终止) |
| ` | ` | |
! | 逻辑非 | 取反,true → false,false → true |
示例
packagemainimport"fmt"funcmain(){a:=trueb:=falsefmt.Println(a&&b)// falsefmt.Println(a||b)// truefmt.Println(!a)// false}3.4 位运算符
对整数二进制位进行操作,底层开发、权限掩码常用。
假定:a=60(0011 1100),b=13(0000 1101)
| 运算符 | 作用 | 结果 |
|---|---|---|
& | 按位与 | 对应位都为1才为1 → 12 |
| ` | ` | 按位或 |
^ | 按位异或 | 对应位不同则为1 → 49 |
<< | 左移 n 位 | 整体左移,低位补0 → a<<2 = 240 |
>> | 右移 n 位 | 整体右移,高位补0 → a>>2 = 15 |
示例
packagemainimport"fmt"funcmain(){varauint=60varbuint=13fmt.Println(a&b)fmt.Println(a|b)fmt.Println(a^b)fmt.Println(a<<2)fmt.Println(a>>2)}3.5 赋值运算符
结合运算 + 赋值,简化代码写法。
| 运算符 | 等价写法 |
|---|---|
= | 基础赋值 |
+= | a = a + b |
-= | a = a - b |
*= | a = a * b |
/= | a = a / b |
%= | a = a % b |
<<= | 左移后赋值 |
>>= | 右移后赋值 |
&= | 按位与后赋值 |
| ` | =` |
^= | 按位异或后赋值 |
示例
packagemainimport"fmt"funcmain(){a:=10a+=5// a = 10 +5fmt.Println(a)a*=2fmt.Println(a)}3.6 其他运算符(地址 & 指针)
| 运算符 | 作用 |
|---|---|
& | 取变量内存地址 |
* | 解引用,取指针指向的值 |
示例
packagemainimport"fmt"funcmain(){a:=4varptr*int// 定义指针变量ptr=&a// 取 a 的地址赋值给指针fmt.Println("a 的地址:",ptr)fmt.Println("a 的值:",*ptr)// 通过指针取值}3.7 运算符优先级
优先级由高到低,同优先级从左向右运算;括号()优先级最高,可手动改变运算顺序。
* / % << >> & &^+ - | ^== != < <= > >=&&||
示例(括号改变优先级)
packagemainimport"fmt"funcmain(){a,b,c,d:=20,10,15,5e:=(a+b)*c/d fmt.Println(e)}