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""(空字符串)
boolfalse
pointer, slice, map, channel, interface, funcnil
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 / uint81B-128127 / 0255
整型int16 / uint162B-3276832767 / 065535
整型int32 / uint324B约 ±21亿 / 0~42亿
整型int64 / uint648B超大整数
整型int / uint4B 或 8B平台相关,32位系统=4B,64位系统=8B
特殊byte1Buint8 的别名,用于原始字节数据
特殊rune4Bint32 的别名,表示一个 Unicode 码点
浮点float324B约 7 位有效数字
浮点float648B约 15 位有效数字(推荐)
复数complex64 / complex1288B/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/runebyte=uint8 原始字节,rune=int32 Unicode 字符
const/iota编译时常量,iota 实现自增枚举
fmt.Printf格式化输出,%v 是万能占位符
字符串不可变修改需 []byte → 修改 → string 转换
strings.Builder大量字符串拼接的高性能方案

上一篇:01-环境与工具链 下一篇:03-复合类型