02 Go 变量与类型学习笔记
Go 变量与类型学习笔记
1. var 声明变量
Go 使用var关键字声明变量,可以指定类型或让编译器推断:
packagemainimport"fmt"funcmain(){varmessage="Hello Variables!"fmt.Println(message)}执行结果:
Hello Variables!要点:
var message = "Hello Variables!"— 省略类型时,编译器根据右值自动推断类型(此处推断为string)var message string = "Hello Variables!"— 显式指定类型var message string— 只声明不赋值,变量获得零值(空字符串"")var声明可在函数内或函数外使用(包级别)
2. 短变量声明(:=)
:=是 Go 最常用的变量声明方式,只能在函数内部使用:
packagemainimport"fmt"funcmain(){count:=42fmt.Printf("Count: %d\n",count)}执行结果:
Count: 42要点:
:=同时完成声明和赋值,编译器自动推断类型(此处推断为int):=只能在函数内部使用,不能用于包级别变量:=左侧必须至少有一个新变量,否则应使用=赋值- 对比
var:var count = 42等价于count := 42,但:=更简洁
3. 批量声明变量(var 分组)
多个变量可以用var()分组声明,更清晰:
packagemainimport"fmt"funcmain(){var(name="Alice"age=30city="Boston")fmt.Printf("Name: %s, Age: %d, City: %s\n",name,age,city)}执行结果:
Name: Alice, Age: 30, City: Boston要点:
var()分组写法适合声明多个相关变量,代码更整洁- 每个变量仍可以单独指定类型或省略类型让编译器推断
- 包级别变量也常用分组写法:
var(globalName="Go"globalAge=10)
4. 类型推断(Type Inference)
当变量声明时省略类型,Go 编译器根据右值自动推断:
packagemainimport"fmt"funcmain(){language:="Go"version:=1.21isActive:=truefmt.Printf("Language: %s %.2f, Active: %t\n",language,version,isActive)}执行结果:
Language: Go 1.21, Active: true要点:
language := "Go"→ 推断为stringversion := 1.21→ 推断为float64(Go 中浮点数字面值默认是float64,不是float32)isActive := true→ 推断为bool- 如果需要特定类型(如
float32),必须显式声明:var version float32 = 1.21
5. 零值(Zero Values)
Go 中声明变量但不赋值时,变量自动获得该类型的零值:
packagemainimport"fmt"funcmain(){varnamestringvarcountintvaractiveboolvarpricefloat64fmt.Printf("String: '%s', Int: %d, Bool: %t, Float: %.1f\n",name,count,active,price)}执行结果:
String: '', Int: 0, Bool: false, Float: 0.0要点:
- 各类型的零值:
string→""(空字符串)int→0bool→falsefloat64→0.0- 指针、切片、映射、通道、接口、函数 →
nil
- Go 没有"未初始化变量"的概念,变量总是有确定的值
- 这避免了 C 语言中未初始化变量带来的安全隐患
6. 常量(Constants)
常量用const声明,值在编译时确定,运行时不可修改:
packagemainimport"fmt"constPI=3.14159constAppName="GoForGo"funcmain(){fmt.Printf("App: %s, PI: %.5f\n",AppName,PI)}执行结果:
App: GoForGo, PI: 3.14159要点:
const声明的值不可修改,尝试修改会编译报错- 常量不能用
:=声明 - 常量的值必须在编译时就能确定(不能是函数返回值等运行时结果)
- 常量也可以分组声明:
const(PI=3.14159AppName="GoForGo") - 特殊常量
iota用于生成递增枚举值:const(Sunday=iota// 0Monday// 1Tuesday// 2)
7. Go 基本类型
Go 提供丰富的内置类型,变量声明时显式指定类型:
packagemainimport"fmt"funcmain(){varnamestring="Go"varversionfloat64=1.21varisOpenbool=truevarusersint=1000000fmt.Printf("Language: %s %.2f, Open: %t, Users: %d\n",name,version,isOpen,users)}执行结果:
Language: Go 1.21, Open: true, Users: 1000000要点:
- Go 的基本类型:
| 类别 | 类型 |
|---|---|
| 整数 | int,int8,int16,int32,int64,uint,uint8…uint64 |
| 浮点 | float32,float64 |
| 布尔 | bool |
| 字符串 | string |
| 字符 | byte(uint8 的别名),rune(int32 的别名,表示 Unicode 字符) |
| 复数 | complex64,complex128 |
int在 64 位系统上是 64 位,32 位系统上是 32 位float64是默认浮点类型,精度比float32更高- 显式指定类型时,
var name string = "Go"和var name = "Go"(推断)效果相同
8. 类型转换(Type Conversion)
Go 不支持隐式类型转换,所有跨类型转换必须显式进行:
packagemainimport("fmt""strconv")funcmain(){// These variables have different typesvarnumberint=42varpifloat64=3.14159varmessagestring="123"floatNumber:=float64(number)intPi:=int(pi)convertedNumber,_:=strconv.Atoi(message)fmt.Printf("Float: %.2f, Int: %d, Converted: %d\n",floatNumber,intPi,convertedNumber)}执行结果:
Float: 42.00, Int: 3, Converted: 123要点:
- 数值类型之间的转换:
float64(number)把int转float64,int(pi)把float64转int int(pi)截断小数部分:3.14159 → 3(不是四舍五入)- 字符串与数值的转换需要
strconv包:strconv.Atoi("123")→ 字符串转整数,返回(int, error)strconv.Itoa(123)→ 整数转字符串strconv.ParseFloat("3.14", 64)→ 字符串转浮点数strconv.FormatFloat(3.14, 'f', 2, 64)→ 浮点数转字符串
- Go 不允许隐式转换:
var f float64 = 42编译报错,必须写var f float64 = float64(42) convertedNumber, _ := strconv.Atoi(message)中_忽略了可能的错误,实际代码中应处理 error
9. 变量作用域(Variable Scope)
变量的可见范围取决于声明位置:包级别 > 函数级别 > 块级别:
packagemainimport"fmt"varglobalMessage="Global"funcmain(){localMessage:="Local"// This will create a new scopeiftrue{blockMessage:="Block"fmt.Printf("%s %s %s\n",globalMessage,localMessage,blockMessage)}// blockMessage is not accessible herefmt.Printf("%s %s\n",globalMessage,localMessage)}执行结果:
Global Local Block Global Local要点:
- 三层作用域:
- 包级别:在所有函数外声明(
var globalMessage = "Global"),整个包内可见 - 函数级别:在函数内声明(
localMessage := "Local"),该函数内可见 - 块级别:在
if、for、switch等代码块内声明(blockMessage := "Block"),只在该块内可见
- 包级别:在所有函数外声明(
- 内层作用域可以访问外层变量(块内可以访问 local 和 global)
- 外层作用域不能访问内层变量(函数外不能访问 blockMessage)
if true是一个永远为真的条件,仅用于演示块作用域
知识点总结
| 知识点 | 关键概念 |
|---|---|
| var 声明 | var name = value可在函数内外使用,可指定或省略类型 |
| 短变量声明 | name := value只能在函数内使用,自动推断类型 |
| 批量声明 | var ()分组声明多个变量,更整洁 |
| 类型推断 | 省略类型时编译器根据右值推断,浮点默认float64 |
| 零值 | 未赋值的变量自动获得零值:string→"", int→0, bool→false, float→0.0 |
| 常量 | const声明不可修改,编译时确定,支持iota枚举 |
| 基本类型 | int/float/bool/string/rune/byte,无隐式转换 |
| 类型转换 | 必须显式转换:float64(i)、int(f),字符串与数值用strconv包 |
| 变量作用域 | 包级 > 函数级 > 块级,内层可见外层,外层不可见内层 |
