外观
Go Variables and Types
Phase 01 — Go Fundamentals 涵盖:
variable·constant·basic types
1. 学习目标
完成本知识点后,你应该能够:
- 使用
var、:=和const声明变量与常量 - 理解 Go 的基本类型及其零值(zero value)
- 知道 Go 是静态强类型语言,不同类型之间必须显式转换
- 区分
var、:=、const的使用场景 - 能编写描述数字孪生设备状态的基础 Go 程序
2. 为什么需要
程序的核心工作是处理数据:设备 ID、坐标、速度、在线状态、电量百分比……这些数据必须先存入变量,Go 编译器才能知道每个值占多少内存、允许哪些操作。
JavaScript 里你可以随时写 let x = 1; x = "hello",类型随意变化。Go 不允许这样做——变量声明时类型就确定了,这是编译型语言安全性的基础,也是后端开发中减少运行时 bug 的关键。
3. 核心概念
3.1 变量(variable)
存储可变数据的命名容器。
| 声明方式 | 语法 | 使用场景 |
|---|---|---|
| 完整声明 | var name type = value | 包级变量、需要零值初始化 |
| 类型推断 | var name = value | 类型 obvious 时 |
| 短声明 | name := value | 函数内部,最常用 |
| 批量声明 | var a, b int = 1, 2 | 多个同类型变量 |
3.2 常量(constant)
编译期确定的不可变值。用 const 声明,值在运行时不能修改。
go
const maxSpeed = 2.0
const Pi = 3.141593.3 基本类型(basic types)
| 类型 | 说明 | 零值 | 示例 |
|---|---|---|---|
bool | 布尔 | false | true, false |
string | 字符串(UTF-8) | "" | "AGV-001" |
int | 整数(平台相关,通常 64 位) | 0 | 42, -7 |
int8/16/32/64 | 固定位宽整数 | 0 | int32(100) |
uint | 无符号整数 | 0 | uint(255) |
float32 | 32 位浮点 | 0.0 | 3.14 |
float64 | 64 位浮点(默认) | 0.0 | 1.5 |
byte | uint8 别名 | 0 | 'A' |
rune | int32 别名,表示 Unicode 码点 | 0 | '中' |
零值(zero value):变量声明后未赋值的默认初始值。Go 保证每个变量都有确定的初始值,不存在 JS 中的
undefined。
3.4 类型转换
Go 不会自动在不同数值类型之间转换,必须显式写:
go
var count int = 10
var ratio float64 = float64(count) / 34. 基础语法
完整可运行示例见 workspace/phase-01/variables/main.go。
go
package main
import "fmt"
func main() {
// 完整声明
var deviceID string = "AGV-001"
var speed float64 = 1.5
// 短声明(函数内推荐)
battery := 85
x, y := 12.5, 3.8
// 常量
const maxSpeed = 2.0
// 类型转换
var count int = 10
ratio := float64(count) / 3
fmt.Println(deviceID, speed, battery, maxSpeed, ratio)
fmt.Printf("position: (%.1f, %.1f)\n", x, y)
}运行:
bash
cd workspace/phase-01/variables
go run main.go5. 代码解析
go
var deviceID string = "AGV-001"完整形式:var + 变量名 + 类型 + 值。类型和值可以省略,此时使用零值。
go
battery := 85:= 是短声明,编译器从右侧值推断类型(这里是 int)。只能在函数内使用,且左侧至少有一个是新变量。
go
x, y := 12.5, 3.8同时声明多个变量,类型分别为 float64。
go
const maxSpeed = 2.0常量在编译期确定,不能重新赋值。命名常量通常用 PascalCase 或 camelCase,全大写仅用于特殊约定。
go
ratio := float64(count) / 3count 是 int,3 也是 untyped int constant,除法结果需要转成 float64 才能赋给浮点变量。
6. JavaScript / TypeScript 对比
| 概念 | Go | JavaScript / TypeScript |
|---|---|---|
| 变量声明 | var x int / x := 1 | let x = 1 / const x = 1 |
| 类型 | 编译期确定,不可变 | JS 运行时动态;TS 编译期检查但编译后消失 |
| 常量 | const 编译期常量 | const 禁止重新赋值,但对象属性仍可改 |
| 未初始化 | 有零值,无 undefined | let x → undefined |
| 类型转换 | 必须显式 float64(n) | 隐式转换或 Number(n) |
| 字符串 | UTF-8,string 不可变 | UTF-16,string 不可变 |
| 整数 | 有 int、int32 等区分 | 只有 Number(IEEE 754 浮点) |
关键差异:
- Go 的
:=只用于函数内;JS 的let/const到处可用 - Go 没有
null/undefined,未赋值的变量是零值 - Go 的
const是真正的编译期常量;JS 的const只是禁止重新绑定 - Go 整数运算是精确的;JS 大整数需要
BigInt
这个概念只能类比理解,底层机制并不相同。
7. 常见错误
错误 1:在函数外使用 :=
go
// ❌ 包级作用域不能用 :=
deviceID := "AGV-001"
// ✅ 包级用 var
var deviceID = "AGV-001"错误 2::= 左侧没有新变量
go
x := 1
x := 2 // ❌ 编译错误:no new variables on left side of :=
x = 2 // ✅ 已声明变量用 =错误 3:隐式类型转换
go
var a int = 10
var b float64 = a // ❌ 编译错误
var b float64 = float64(a) // ✅错误 4:混淆 byte 和 rune
go
var ch byte = '中' // ❌ '中' 超出 byte 范围
var ch rune = '中' // ✅错误 5:用 var 声明却期望短声明的推断行为
go
var speed = 1.5 // float64,OK
var speed float64 // 零值 0.0,不是 1.5
speed = 1.58. 实际应用
数字孪生 — AGV 设备状态
后端接收并处理 AGV 实时数据时,变量和类型是最基础的构建块:
go
var agvID string = "AGV-001"
var positionX float64 = 12.5
var positionY float64 = 3.8
var speed float64 = 1.2
var battery int = 85
var isOnline bool = true
const maxSpeed = 2.0
const lowBatteryThreshold = 20后续你会用 struct 把这些字段组合成一个设备对象,用 JSON 序列化后通过 WebSocket 推送给 Three.js 前端。
Web API 中的类型选择
| 场景 | 推荐类型 | 原因 |
|---|---|---|
| 设备 ID | string | 可能含字母前缀 |
| 坐标 / 速度 | float64 | 需要小数精度 |
| 电量百分比 | int | 0–100 整数 |
| 在线状态 | bool | 二值 |
| 时间戳 | int64 | Unix 毫秒 |
9. 深入理解
9.1 静态类型 vs 动态类型
Go 在编译期检查类型,类型错误在 go build 时就会报错,不会等到运行时。这对后端服务意味着:上线前的编译就是第一道质量关卡。
9.2 零值的设计哲学
Go 设计者认为:变量应该有确定的初始状态,而不是 undefined 或随机内存值。这让代码行为可预测,减少空指针类 bug。
9.3 untyped constant
go
const x = 1 + 2 // untyped constant,使用时根据上下文确定类型
var a int = x // OK
var b float64 = x // OK常量表达式在编译期计算,没有类型直到被使用时才确定。
9.4 int 的大小
Go 的 int 大小取决于平台(32 位系统 32 位,64 位系统 64 位)。需要精确位宽时用 int32、int64。
10. 练习
请独立完成,不要查看答案。完成后说「检查答案」并提交你的代码。
Level 1 — 基础
练习 1.1:声明变量存储以下 AGV 信息并打印:
- 设备 ID(string):
"AGV-002" - 速度(float64):
0.8 - 是否在线(bool):
true
练习 1.2:使用 := 短声明三个变量 name、level、active,分别赋值为 "sensor-01"、3、true,打印它们的值和类型(提示:fmt.Printf("%T", x))。
练习 1.3:声明一个 float64 变量但不赋值,打印它的零值。
Level 2 — 应用
练习 2.1:定义常量 warehouseWidth = 100.0 和 warehouseHeight = 50.0,声明变量 agvX = 30.0 和 agvY = 10.0,计算 AGV 到仓库中心 (width/2, height/2) 的距离并打印。
距离公式:
sqrt((x2-x1)² + (y2-y1)²),使用math.Sqrt
练习 2.2:声明 battery int = 15,用常量 lowBatteryThreshold = 20,判断电量是否低于阈值,打印 "low battery warning" 或 "battery ok"。
练习 2.3:有变量 distance int = 150 和 duration float64 = 12.5,计算平均速度 float64(distance) / duration 并打印(保留 2 位小数)。
Level 3 — 综合
练习 3.1:模拟 3 台 AGV 的基础信息(ID、X 坐标、Y 坐标、速度),使用变量和常量完成,打印每台设备的信息和到原点的距离。
练习 3.2:定义设备状态常量 Idle、Moving、Error(string 类型),声明变量表示当前状态,编写逻辑打印 "AGV-001 is moving at 1.2 m/s" 格式的字符串。
Level 4 — 项目实践
练习 4.1:在 workspace/phase-01/variables/ 下创建 agv_status.go,模拟一个数字孪生 AGV 状态快照:
- 用变量存储:ID、位置 X/Y、速度、电量、在线状态
- 用常量定义:最大速度、低电量阈值、仓库边界
- 打印完整状态报告,包含是否超速、是否低电量的判断结果
- 确保
go run agv_status.go可以正常运行
11. 学习检查
完成练习后,确认你能回答:
var、:=、const分别在什么场景使用?- Go 的零值是什么?与 JS 的
undefined有何不同? - 为什么
var b float64 = a(a 是 int)会编译失败? byte和rune有什么区别?- 函数内和函数外声明变量有什么区别?
- 如何选择
intvsfloat64vsstring?
12. 下一步
| 已完成 | 下一知识点 | 关系 |
|---|---|---|
| variable, constant, basic types | array | 单个变量 → 同类型变量集合 |
| slice | 动态数组,Go 最常用的集合类型 | |
| struct | 将多个变量组合成设备对象 |
建议顺序:array → slice → map → struct,之后就能建模完整的 AGV 设备数据结构。
前置知识提醒
你跳过了 Phase 01 的前 3 个知识点(Go 环境、go mod、package)。运行代码前请确认:
- 已安装 Go(
go version可执行) - 每个
.go文件开头有package main - 使用
go run main.go运行
如需补学,可以说「学习 Go 环境」或「学习 package」。