下载工作台
Go 编程实战

变量、类型与常量

试读上半部分 · 解锁后可读全文

第 2 章 · 变量、类型与常量

本章目标:掌握 Go 短变量声明:=)、基本类型、零值、常量与 iota 枚举;理解 值类型与引用类型(slice/map/chan 预告);熟练使用 fmt 格式化显式类型转换;在 toolkit-go 中定义订单状态常量与商品价格字段(为单位);对照 java-dev ch02 基本类型与 python-dev ch02 动态类型。

学时建议:3~4 小时(含 1 小时跟练)

前置:完成 go-dev ch01,能运行 toolkit-go;建议已浏览 java-dev ch02 变量与类型。


2.1 场景说明:toolkit-go 需要强类型数据

toolkit-go(目录 ~/learn-go/toolkit-go,Windows 为 %USERPROFILE%\learn-go\toolkit-go)在 ch15 将解析 access 日志并统计慢请求。本章先在 internal/model/ 中定义与商城对齐的基础类型:订单状态用 常量枚举,商品价格用 int64 存储,避免浮点误差(与 django-web / fastapi-web / gin-webslug + is_published 字段约定一致,价格语义对齐)。

字段Go 类型Java 对照Python 对照
商品 slugstringStringstr
价格int64(分)long / BigDecimalintDecimal
是否上架boolbooleanbool
订单状态const + iotaenum字符串或 IntEnum
learn-go/toolkit-go/
├── go.mod
├── cmd/toolkit/main.go
└── internal/
    └── model/
        ├── order_status.go    # 本章:状态常量
        ├── product_stub.go    # 本章:商品桩
        └── money.go           # 本章:元分转换

2.2 变量声明方式

Go 提供三种常见声明方式,编译器在编译期确定类型(静态类型)。

// internal/model/vars_demo.go — 教学示例,可删除
package model

// 包级变量:须显式类型或使用 var 推断
var AppName string = "toolkit-go"
var DefaultTopN = 10

func DemoVars() {
	// 短声明:仅函数内,类型由编译器推断
	port := 8080
	host := "127.0.0.1"

	// 多变量
	var x, y int = 1, 2
	a, b := 3, 4

	_ = port
	_ = host
	_ = x
	_ = y
	_ = a
	_ = b
}
方式语法适用场景
var x T = v显式类型包级变量、需零值初始化
var x = v类型推断包级或函数内
x := v短声明仅函数内,最常用
JavaGoPython
int x = 10;x := 10var x int = 10x = 10
必须先声明类型短声明可推断无声明关键字
包级无 :=包级无 :=无此限制
注意:包级变量不能使用 :=;未使用的局部变量会导致编译错误(Go 强制「声明即使用」)。用 _ 丢弃不需要的值。

2.3 基本类型与零值

Go 每种类型都有明确的零值(zero value),变量声明后未赋值即为零值。

类型零值toolkit-go 示例
boolfalse日志行是否慢请求
int / int32 / int640响应耗时毫秒、Price(分)
float32 / float640.0仅展示用,不存金额
string""商品 slug、日志路径
byte / rune0字节 / Unicode 码点
*Tnil可选指针字段
errornil函数错误返回值(接口类型)
slice / map / channilch04 详讲
// internal/model/product_stub.go
package model

import "fmt"

type ProductStub struct {
	Slug        string
	Price       int64 // 分:6800 表示 68.00 元
	IsPublished bool
}

func NewProductStub(slug string, priceYuan float64) ProductStub {
	cents := YuanToCents(priceYuan)
	return ProductStub{Slug: slug, Price: cents, IsPublished: false}
}

func (p ProductStub) PriceYuan() string {
	return fmt.Sprintf("%.2f", float64(p.Price)/100)
}
Java(java-dev)Go(go-dev)Python
成员变量有默认值所有类型零值明确无「未初始化」概念
long price = 6800Lprice := int64(6800)price = 6800
隐式窄化可能编译失败必须显式转换动态转换

2.4 整数、浮点与字符串

分类Go 类型说明
有符号整数int8int64intint 长度随平台(32/64 位)
无符号整数uint8uint64uint位运算、哈希
浮点float32float64默认浮点字面量为 float64
复数complex64complex128科学计算,本课少用
字符串stringUTF-8 字节序列,不可变
字节 / 字符byte(=uint8)、rune(=int32)处理 ASCII / Unicode
package model

import (
	"fmt"
	"unicode/utf8"
)

func DemoTypes() {
	var stock int64 = 100
	var rate float64 = 0.15
	slug := "go-handbook"
	ch := 'G' // rune

	fmt.Println(stock, rate, slug, string(ch))
	fmt.Println(utf8.RuneCountInString("Go语言")) // 4 个 rune
}

金额规范(全站统一)

错误做法正确做法
float64 存储 68.99 元int64 存储 6899 分
浮点加减产生 0.1+0.2 问题整数分运算精确
JSON 传 "price": 68.99"price": 6899(分)

2.5 常量与 iota 枚举

// internal/model/order_status.go
package model

// 订单状态 — 整数枚举(iota)
const (
	OrderPending = iota // 0
	OrderPaid           // 1
	OrderShipped        // 2
	OrderCancelled      // 3
)

// 对外 API / JSON 友好字符串常量
const (
	StatusPending   = "pending"
	StatusPaid      = "paid"
	StatusShipped   = "shipped"
	StatusCancelled = "cancelled"
)

// 应用版本 — 普通常量
const Version = "0.1.0"

// HTTP 状态码子集(iota 跳过示例)
const (
	HTTPStatusOK       = 200
	HTTPStatusCreated  = 201
	HTTPStatusBadReq   = 400
	HTTPStatusNotFound = 404
	HTTPStatusServer   = 500
)
模式说明Java 对照
iota 自增同一 const 块内从 0 递增enum 序号
字符串常量序列化 / API 边界enum.name() 或字符串字段
const逻辑分组public static final 一组

iota 高级模式(选修)

const (
	_  = iota             // 跳过 0
	KB = 1 << (10 * iota) // 1 << 10, 1 << 20 ...
	MB
	GB
)

Go 1.21+ 可用 type OrderStatus int 增强类型安全(类似 Java enum 包装),本课以 iota + 字符串常量为主。


2.6 类型转换(无隐式转换)

Go 无隐式数值转换,必须显式 cast。这与 Java 部分场景(如 intlong widening)和 Python 动态转换均不同。

// internal/model/money.go
package model

import "math"

func YuanToCents(yuan float64) int64 {
	return int64(math.Round(yuan * 100))
}

func CentsToYuan(cents int64) float64 {
	return float64(cents) / 100
}

func DemoConvert() {
	var durationMs int = 1500
	var seconds float64 = float64(durationMs) / 1000

	cents := YuanToCents(68.99) // 6899
	_ = seconds
	_ = cents
}
错误写法正确写法说明
var f float64 = 10(int 赋 float)var f float64 = float64(10)必须显式
int64(3.14) 直接截断math.Round 再转避免静默丢精度
float64 存分int64 存分业务规范
string(65) 得 Unicodestrconv.Itoa(65)"65"类型转换语义不同

以下内容需解锁后阅读

试读已结束。解锁本章 ¥5.00,或开通年度会员畅读全部教程。
年度会员 ¥199.00/年; 小紫 AI 工作台有效会员 ¥99.00/年

正文仅在服务端鉴权后下发,未付费无法获取下半部分内容。