Go 的变量声明、基本类型与类型系统基础
一、变量声明
Go 是静态类型语言——变量的类型在编译时确定。
1.1 四种声明方式
// 1. var 显式声明(指定类型)
var name string = "Go"
// 2. var 显式声明(类型推断)
var name = "Go"
// 3. := 短变量声明(最常用,只能在函数内使用)
name := "Go"
// 4. var 批量声明
var (
age int = 25
height float64 = 175.5
isGo bool = true
)
1.2 := 的限制
// ✅ 函数内部 — 可以用 :=
func main() {
x := 10
fmt.Println(x)
}
// ❌ 包级别 — 不能用 :=,必须用 var
var globalVar = "ok"
// globalVar := "fail" // 编译错误
1.3 零值
Go 中未赋值的变量自动初始化为零值(不是 undefined 或 null):
| 类型 | 零值 |
|---|---|
int, float64 等数值类型 | 0 |
string | ""(空字符串) |
bool | false |
pointer, slice, map, channel, interface, func | nil |
array | 按元素类型填充零值 |
struct | 每个字段填充零值 |
var (
i int // 0
f float64 // 0
b bool // false
s string // ""
p *int // nil
)
fmt.Println(i, f, b, s, p) // 0 0 false "" <nil>
Go 的哲学:所有变量都有确定的初始值。 这消除了大量"未初始化"导致的 bug。
二、基本类型
2.1 数值类型
| 类别 | 类型 | 大小 | 范围/说明 |
|---|---|---|---|
| 整型 | int8 / uint8 | 1B | -128 |
| 整型 | int16 / uint16 | 2B | -32768 |
| 整型 | int32 / uint32 | 4B | 约 ±21亿 / 0~42亿 |
| 整型 | int64 / uint64 | 8B | 超大整数 |
| 整型 | int / uint | 4B 或 8B | 平台相关,32位系统=4B,64位系统=8B |
| 特殊 | byte | 1B | uint8 的别名,用于原始字节数据 |
| 特殊 | rune | 4B | int32 的别名,表示一个 Unicode 码点 |
| 浮点 | float32 | 4B | 约 7 位有效数字 |
| 浮点 | float64 | 8B | 约 15 位有效数字(推荐) |
| 复数 | complex64 / complex128 | 8B/16B | 科学计算用 |
// 类型转换:Go 不做隐式转换,必须显式
var a int32 = 100
var b int64 = int64(a) // ✅ 显式转换
// var c int64 = a // ❌ 编译错误
// 常见陷阱:int 和 float64 不能隐式混合运算
var x int = 10
var y float64 = 3.14
// var z = x + y // ❌ 类型不匹配
var z = float64(x) + y // ✅ 需要显式转换
2.2 字符串
// 基本声明
s1 := "Hello, Go"
s2 := `这是原始字符串
可以换行
不支持转义\n` // 反引号:raw string literal
// 字符串操作
len(s1) // 长度(字节数,不是字符数)
s1[0] // 第一个字节:'H'(byte 类型)
for i, ch := range s1 { // 遍历:i 是字节索引,ch 是 rune
fmt.Printf("%d: %c\n", i, ch)
}
// 字符串是不可变的
// s1[0] = 'h' // ❌ 编译错误
// 修改字符串:转 []byte 再转回来
b := []byte(s1)
b[0] = 'h'
s1 = string(b) // "hello, Go"
// 拼接
// 少量拼接:+ 号即可
result := "Hello" + ", " + "Go"
// 大量拼接:用 strings.Builder(高性能)
var builder strings.Builder
for i := 0; i < 1000; i++ {
builder.WriteString("item")
}
result := builder.String()
2.3 布尔类型
var flag bool // 零值 false
flag = true
flag = false
// 布尔运算
a && b // 与
a || b // 或
!a // 非
// ⚠️ Go 中 if 条件不需要括号,但条件必须是 bool 类型
if flag {
fmt.Println("true")
}
// if 1 { ... } // ❌ Go 不允许整数当布尔用
2.4 类型别名与可读性增强
// type 关键字创建自定义类型
type UserID int64
type Celsius float64
type Status string
// 自定义类型可以定义方法(后续章节详述)
func (c Celsius) Fahrenheit() float64 {
return float64(c)*9/5 + 32
}
// 使用自定义类型提高可读性
func GetUser(id UserID) string { ... }
// 注意:自定义类型是新类型,不能直接和原始类型混合运算
var uid UserID = 100
// var n int = uid // ❌ 类型不匹配
var n int = int(uid) // ✅ 需要显式转换
三、常量
3.1 基本常量
const Pi = 3.14159265358979
const (
StatusOK = 200
StatusError = 500
)
// 常量必须是编译时可确定的值
const x = 10 + 20 // ✅
// const y = someFunc() // ❌ 运行时值不能赋给常量
3.2 iota 枚举器
iota 是 Go 的常量计数器,在每个 const 块中从 0 开始自增:
type Weekday int
const (
Sunday Weekday = iota // 0
Monday // 1
Tuesday // 2
Wednesday // 3
Thursday // 4
Friday // 5
Saturday // 6
)
iota 的进阶用法:
const (
_ = iota // 0,丢弃
KB = 1 << (10 * iota) // 1 << 10 = 1024
MB // 1 << 20 = 1048576
GB // 1 << 30
TB // 1 << 40
)
// 带表达式的 iota
const (
ReadOnly = 1 << iota // 1 (1 << 0)
WriteOnly // 2 (1 << 1)
ExecuteOnly // 4 (1 << 2)
)
// 可以组合权限:perm = ReadOnly | WriteOnly => 3
四、类型转换规则
4.1 显式转换(必须)
// Go 不支持隐式类型转换,一切都要显式
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
var s string = string(65) // "A"(Unicode 码点 65 → 字符)
var bs []byte = []byte("Hi") // []byte{72, 105}
4.2 转换注意点
// 浮点 → 整型:截断小数(不是四舍五入)
var f float64 = 3.99
var i int = int(f) // i = 3,不是 4
// 大范围 → 小范围:可能溢出
var big int32 = 100000
var small int8 = int8(big) // 小范围溢出:结果不可预测
// 字符串 ↔ []byte/[]rune
s := "Hello"
bytes := []byte(s) // UTF-8 编码的字节切片
runes := []rune(s) // Unicode 码点切片
五、fmt 包常用函数
开发阶段最常用的打印工具:
import "fmt"
// Print 系列:不自动换行
fmt.Print("hello") // 打印到标准输出
fmt.Println("hello") // 打印 + 换行(最常用)
fmt.Printf("name: %s, age: %d\n", name, age) // 格式化输出
// Sprint 系列:返回字符串(不打印)
s := fmt.Sprintf("name: %s", name)
// Fprint 系列:写入指定的 writer
fmt.Fprintf(os.Stdout, "to stdout\n")
// 格式化动词速查
// %v 默认格式(万能)
// %d 整数
// %f 浮点数
// %s 字符串
// %t 布尔值
// %p 指针地址
// %T 类型名称
// %+v 结构体带字段名输出(调试用)
// %#v Go 语法表示(调试用)
六、本节要点速查
| 概念 | 要点 |
|---|---|
:= | 短变量声明,函数内最常用的声明方式 |
| 零值 | 所有变量自动初始化为确定的零值 |
| 类型转换 | Go 不做隐式转换,必须显式 Type(x) |
int | 平台相关(32/64位),不确定时用 int64 |
float64 | 浮点数首选(精度够用) |
byte/rune | byte=uint8 原始字节,rune=int32 Unicode 字符 |
const/iota | 编译时常量,iota 实现自增枚举 |
fmt.Printf | 格式化输出,%v 是万能占位符 |
| 字符串不可变 | 修改需 []byte → 修改 → string 转换 |
strings.Builder | 大量字符串拼接的高性能方案 |
豫公网安备41108202000982号