Skip to content

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.14159

3.3 基本类型(basic types)

类型说明零值示例
bool布尔falsetrue, false
string字符串(UTF-8)"""AGV-001"
int整数(平台相关,通常 64 位)042, -7
int8/16/32/64固定位宽整数0int32(100)
uint无符号整数0uint(255)
float3232 位浮点0.03.14
float6464 位浮点(默认)0.01.5
byteuint8 别名0'A'
runeint32 别名,表示 Unicode 码点0'中'

零值(zero value):变量声明后未赋值的默认初始值。Go 保证每个变量都有确定的初始值,不存在 JS 中的 undefined

3.4 类型转换

Go 不会自动在不同数值类型之间转换,必须显式写:

go
var count int = 10
var ratio float64 = float64(count) / 3

4. 基础语法

完整可运行示例见 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.go

5. 代码解析

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) / 3

countint3 也是 untyped int constant,除法结果需要转成 float64 才能赋给浮点变量。


6. JavaScript / TypeScript 对比

概念GoJavaScript / TypeScript
变量声明var x int / x := 1let x = 1 / const x = 1
类型编译期确定,不可变JS 运行时动态;TS 编译期检查但编译后消失
常量const 编译期常量const 禁止重新赋值,但对象属性仍可改
未初始化有零值,无 undefinedlet xundefined
类型转换必须显式 float64(n)隐式转换或 Number(n)
字符串UTF-8,string 不可变UTF-16,string 不可变
整数intint32 等区分只有 Number(IEEE 754 浮点)

关键差异

  1. Go 的 := 只用于函数内;JS 的 let/const 到处可用
  2. Go 没有 null/undefined,未赋值的变量是零值
  3. Go 的 const 是真正的编译期常量;JS 的 const 只是禁止重新绑定
  4. 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:混淆 byterune

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.5

8. 实际应用

数字孪生 — 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 中的类型选择

场景推荐类型原因
设备 IDstring可能含字母前缀
坐标 / 速度float64需要小数精度
电量百分比int0–100 整数
在线状态bool二值
时间戳int64Unix 毫秒

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 位)。需要精确位宽时用 int32int64


10. 练习

请独立完成,不要查看答案。完成后说「检查答案」并提交你的代码。

Level 1 — 基础

练习 1.1:声明变量存储以下 AGV 信息并打印:

  • 设备 ID(string):"AGV-002"
  • 速度(float64):0.8
  • 是否在线(bool):true

练习 1.2:使用 := 短声明三个变量 namelevelactive,分别赋值为 "sensor-01"3true,打印它们的值和类型(提示:fmt.Printf("%T", x))。

练习 1.3:声明一个 float64 变量但不赋值,打印它的零值。

Level 2 — 应用

练习 2.1:定义常量 warehouseWidth = 100.0warehouseHeight = 50.0,声明变量 agvX = 30.0agvY = 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 = 150duration float64 = 12.5,计算平均速度 float64(distance) / duration 并打印(保留 2 位小数)。

Level 3 — 综合

练习 3.1:模拟 3 台 AGV 的基础信息(ID、X 坐标、Y 坐标、速度),使用变量和常量完成,打印每台设备的信息和到原点的距离。

练习 3.2:定义设备状态常量 IdleMovingError(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. 学习检查

完成练习后,确认你能回答:

  1. var:=const 分别在什么场景使用?
  2. Go 的零值是什么?与 JS 的 undefined 有何不同?
  3. 为什么 var b float64 = a(a 是 int)会编译失败?
  4. byterune 有什么区别?
  5. 函数内和函数外声明变量有什么区别?
  6. 如何选择 int vs float64 vs string

12. 下一步

已完成下一知识点关系
variable, constant, basic typesarray单个变量 → 同类型变量集合
slice动态数组,Go 最常用的集合类型
struct将多个变量组合成设备对象

建议顺序:arrayslicemapstruct,之后就能建模完整的 AGV 设备数据结构。


前置知识提醒

你跳过了 Phase 01 的前 3 个知识点(Go 环境、go mod、package)。运行代码前请确认:

  1. 已安装 Go(go version 可执行)
  2. 每个 .go 文件开头有 package main
  3. 使用 go run main.go 运行

如需补学,可以说「学习 Go 环境」或「学习 package」。


学习导航

上一篇:package · 对应练习 · 下一篇:array 与 slice