返回首页

Golang入门:1.2 基本语法与数据类型

1.2.1 变量声明与初始化

Go 语言提供了多种变量声明方式,灵活且类型安全。

使用 var 关键字声明

var 是 Go 中最基本的变量声明方式,适用于包级别和函数级别。

// 声明单个变量(指定类型)
var name string
var age int

// 声明并初始化
var city string = "Beijing"
var count int = 42

// 类型推断(省略类型)
var message = "Hello, Go!"
var pi = 3.14159

短变量声明 :=

短变量声明是 Go 中最常用的声明方式,只能在函数内部使用

func main() {
    // 短变量声明,自动推断类型
    name := "Go语言"
    version := 1.21
    isStable := true

    // 重新赋值(已声明的变量不能再次使用 :=)
    name = "Golang"
}

注意: := 不能用于包级别(函数外部),且左侧必须至少有一个新变量。

多变量声明

Go 支持一次声明多个变量,提高代码可读性。

// 多变量同时声明
var x, y, z int

// 多变量声明并初始化(类型可不同)
var (
    username string = "admin"
    port     int    = 8080
    debug    bool   = false
)

// 短变量声明多个变量
a, b, c := 1, "hello", true
声明方式 语法 适用场景
var x int 显式类型,无初始值 需要零值初始化、包级变量
var x = value 类型推断 初始值类型明确、包级变量
x := value 短变量声明 函数内部,最常用方式
var (...) 批量声明 多个相关变量的集中声明

1.2.2 常量与 iota 枚举

常量声明

常量使用 const 关键字声明,值在编译期确定,不可修改。

// 单个常量
const Pi = 3.14159265358979
const AppName string = "MyApp"

// 批量声明
const (
    StatusOK       = 200
    StatusNotFound = 404
    StatusError    = 500
)

iota 枚举器

iota 是 Go 的常量计数器,在 const 块中从 0 开始自增,是实现枚举的惯用方式。

// 基本用法:从 0 开始自增
const (
    Sunday    = 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
    GB                     // 1 << 30
    TB                     // 1 << 40
)

// 自定义表达式
const (
    FlagRead    = 1 << iota // 1
    FlagWrite               // 2
    FlagExecute             // 4
)

iota 规则总结:

  • 每个 const 块中 iota 从 0 开始
  • 每新增一行常量声明,iota 自增 1
  • 同一行多个 iota 值相同
  • 不同 const 块的 iota 互相独立

1.2.3 基本数据类型

Go 是强类型语言,提供了丰富的内置数据类型。

整型

类型 大小 范围 说明
int8 1 字节 -128 ~ 127 有符号 8 位整数
int16 2 字节 -32768 ~ 32767 有符号 16 位整数
int32 4 字节 -2^31 ~ 2^31-1 有符号 32 位整数
int64 8 字节 -2^63 ~ 2^63-1 有符号 64 位整数
uint8 1 字节 0 ~ 255 无符号 8 位(即 byte
uint16 2 字节 0 ~ 65535 无符号 16 位整数
uint32 4 字节 0 ~ 2^32-1 无符号 32 位整数
uint64 8 字节 0 ~ 2^64-1 无符号 64 位整数
int 平台相关 32 或 64 位 最常用,随平台变化
uint 平台相关 32 或 64 位 无符号,随平台变化
uintptr 平台相关 足以存放指针 用于底层编程
var (
    a int     = 42
    b int64   = 9223372036854775807
    c uint8   = 255
    d byte    = 'A' // byte 是 uint8 的别名
    e rune    = '中' // rune 是 int32 的别名,表示 Unicode 码点
)

浮点型

类型 大小 精度
float32 4 字节 约 6-7 位有效数字(IEEE 754 单精度)
float64 8 字节 约 15-16 位有效数字(IEEE 754 双精度,推荐使用
var (
    f1 float32 = 3.14
    f2 float64 = 3.141592653589793
    f3         = 2.718 // 默认推断为 float64
)

// 复数类型
var (
    c1 complex64  = 1 + 2i
    c2 complex128 = complex(3.0, 4.0)
)

布尔型

布尔类型只有 truefalse 两个值,不能与整型互相转换。

var (
    isActive bool = true
    isDone   bool = false
    flag          = true // 类型推断
)

// 布尔运算
result := (10 > 5) && (3 != 4) // true

💡 Go 与其他语言的区别: Go 中布尔值不能隐式转换为 0/1,if 1 { } 这种写法是非法的。

字符串

Go 中字符串是不可变的 UTF-8 编码字节序列。

var (
    s1 string = "Hello, 世界"
    s2        = "Go is awesome"
    s3        = `这是原始字符串字面量
支持多行
不处理转义符 \n`
)

// 字符串操作
length := len(s1)               // 字节长度
runeLen := utf8.RuneCountInString(s1) // 字符数量
concat := s1 + " " + s2        // 字符串拼接
sub := s1[0:5]                  // 切片(按字节)
常用字符串操作 说明
strings.Contains(s, sub) 判断是否包含子串
strings.Split(s, sep) 按分隔符切割
strings.Join(slice, sep) 连接字符串切片
strings.Replace(s, old, new, n) 替换子串
fmt.Sprintf(format, args...) 格式化拼接
strconv.Itoa(n) / strconv.Atoi(s) 整数与字符串互转

1.2.4 类型转换与类型推断

显式类型转换

Go 不支持隐式类型转换,所有类型转换必须显式进行。

// 语法:T(expression)
var i int = 42
var f float64 = float64(i)  // int → float64
var u uint = uint(f)        // float64 → uint

// 字符串与数字转换
import "strconv"

s := strconv.Itoa(42)         // int → string: "42"
n, err := strconv.Atoi("42") // string → int: 42

// 字符串与字节切片互转
bytes := []byte("hello")     // string → []byte
str := string(bytes)         // []byte → string

🔔 类型转换的安全注意事项:

  • 大范围转小范围可能溢出(如 int64int8
  • 浮点转整数会截断小数部分(非四舍五入)
  • 字符串转 []byte拷贝数据

类型推断

Go 编译器能根据右侧的值自动推断变量类型。

// 编译器自动推断类型
i := 42          // int
f := 3.14        // float64
s := "hello"     // string
b := true        // bool
c := 3 + 4i     // complex128

// 函数返回值推断
result := someFunction() // 类型由函数签名决定

推断规则如下:

字面量形式 推断类型 示例
整数字面量 int x := 100
浮点数字面量 float64 x := 3.14
复数字面量 complex128 x := 1 + 2i
字符串字面量 string x := "hi"
布尔字面量 bool x := true
字符字面量(rune) rune(即 int32 x := 'A'

1.2.5 零值(Zero Value)机制

Go 中所有变量在声明时如果没有显式赋值,会被自动初始化为该类型的零值。这一机制消除了未初始化变量的安全隐患。

var (
    i int        // 0
    f float64    // 0.0
    b bool       // false
    s string     // ""(空字符串)
    p *int       // nil
    sl []int     // nil
    m map[string]int // nil
    ch chan int  // nil
    fn func()   // nil
    iface error // nil
)

各类型零值速查

类型 零值 备注
整型(int, int8 等) 0 所有整型统一为 0
浮点型(float32, float64 0.0
布尔型(bool false
字符串(string ""(空字符串) 长度为 0,非 nil
指针(*T nil
切片([]T nil nil 切片可安全 append
映射(map[K]V nil nil map 读取安全,写入 panic
通道(chan T nil nil channel 永久阻塞
接口(interface nil
函数(func nil
结构体(struct 各字段的零值 递归应用零值规则
数组([N]T 各元素的零值 长度固定,每个元素为零值

零值的实际应用

// 零值可直接使用的设计模式
var buf bytes.Buffer // 无需 make,零值即可用
buf.WriteString("hello")

var mu sync.Mutex // 零值即为未锁定状态
mu.Lock()
defer mu.Unlock()

// 利用零值判断是否已初始化
type Config struct {
    Host string
    Port int
}

var cfg Config
if cfg.Host == "" { // 利用零值判断
    cfg.Host = "localhost"
}
if cfg.Port == 0 {
    cfg.Port = 8080
}

零值设计哲学: Go 的零值机制体现了 "make the zero value useful"(让零值有用)的设计理念。许多标准库类型(如 bytes.Buffersync.Mutexsync.WaitGroup)都被设计为零值即可使用,无需额外初始化。


小结

核心要点:

  • var 用于包级和函数级声明,:= 仅限函数内部
  • const + iota 是 Go 实现枚举的惯用方式
  • Go 是强类型语言,不允许隐式类型转换
  • 零值机制保证变量始终有确定的初始状态

最佳实践:

  • 优先使用 := 进行局部变量声明
  • 使用 var 块集中管理相关变量
  • 类型转换时注意溢出和精度丢失
  • 善用零值设计,减少不必要的初始化代码
上一篇

Golang入门:1.1从诞生哲学到 Hello World 深度解析

下一篇

Golang入门:1.3 流程控制