第03章 - 基础语法与数据类型
本章系统讲解 Go 的基础语法元素:变量、常量、基本数据类型、运算符以及类型转换,这是编写任何 Go 程序的根基。
3.1 程序结构与包
每个 Go 源文件都以 package 声明开头,表明它属于哪个包。同一目录下的所有文件必须属于同一个包。
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.Pi)
}
- 多个导入可以用括号分组书写。
- 导入的包如果没有被使用,会导致编译错误——这是 Go 强制简洁的体现。
- 同样,声明但未使用的局部变量也会导致编译失败。
3.2 变量声明
3.2.1 标准声明
使用 var 关键字声明变量:
var name string = "Go"
var age int = 15
var isStable bool = true
3.2.2 类型推断
如果提供了初始值,可以省略类型,由编译器自动推断:
var name = "Go" // 推断为 string
var age = 15 // 推断为 int
3.2.3 短变量声明
在函数内部,最常用的是 := 短变量声明,它同时完成声明和初始化:
func main() {
name := "Go"
age := 15
pi := 3.14
}
注意:
:=只能在函数内部使用,不能用于包级别变量声明。
3.2.4 批量声明
var (
host string = "localhost"
port int = 8080
debug bool = false
)
3.2.5 零值
Go 中所有变量在声明时若未显式初始化,都会被赋予该类型的零值,绝不会是未定义的随机值:
| 类型 | 零值 |
|---|---|
| 数值类型(int、float 等) | 0 |
| 布尔类型 | false |
| 字符串 | ""(空字符串) |
| 指针、切片、map、channel、函数、接口 | nil |
var i int // 0
var f float64 // 0.0
var s string // ""
var b bool // false
var p *int // nil
3.3 常量
常量使用 const 声明,其值在编译期确定,不可修改:
const Pi = 3.14159
const (
StatusOK = 200
StatusNotFound = 404
)
3.3.1 iota 枚举
iota 是 Go 的常量计数器,在 const 块中从 0 开始,每行自增 1,常用于定义枚举:
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
)
3.4 基本数据类型
3.4.1 整型
Go 提供了丰富的整型,分为有符号和无符号两类:
| 类型 | 位数 | 范围说明 |
|---|---|---|
int8 / uint8 |
8 | uint8 即 byte |
int16 / uint16 |
16 | |
int32 / uint32 |
32 | int32 即 rune |
int64 / uint64 |
64 | |
int / uint |
平台相关 | 32 位系统为 32 位,64 位系统为 64 位 |
uintptr |
平台相关 | 存放指针的整数 |
建议:除非有特殊需求(如二进制协议、性能优化),整数一律使用
int。
3.4.2 浮点型
float32:单精度,约 7 位有效数字。float64:双精度,约 15 位有效数字,是默认和推荐的浮点类型。
var pi float64 = 3.141592653589793
由于浮点数存在精度问题,比较两个浮点数是否相等时应判断差值是否小于一个极小值,而非直接用 ==。
3.4.3 复数
Go 原生支持复数类型 complex64 和 complex128:
c := complex(3, 4) // 3+4i
fmt.Println(real(c), imag(c)) // 3 4
3.4.4 布尔型
bool 类型只有 true 和 false 两个值。注意 Go 中布尔值不能与整数互相转换。
3.4.5 字符串
字符串是不可变的字节序列,底层使用 UTF-8 编码:
s := "Hello, 世界"
fmt.Println(len(s)) // 13(字节数,中文每个占 3 字节)
fmt.Println(s[0]) // 72(byte 值)
- 双引号字符串支持转义字符(
\n、\t等)。 - 反引号(
`)定义原始字符串,不转义,可跨行,常用于正则表达式或多行文本:
raw := `第一行
第二行 带制表符
路径: C:\Users`
3.4.6 byte 与 rune
byte是uint8的别名,表示一个字节。rune是int32的别名,表示一个 Unicode 码点(字符)。
遍历字符串时,使用 range 会按 rune(字符)迭代,正确处理多字节字符:
for i, r := range "Go语言" {
fmt.Printf("索引 %d: 字符 %c (码点 %d)\n", i, r, r)
}
3.5 运算符
3.5.1 算术运算符
+、-、*、/、%(取余)。注意整数相除会舍弃小数部分。
3.5.2 比较运算符
==、!=、<、<=、>、>=,返回布尔值。
3.5.3 逻辑运算符
&&(与)、||(或)、!(非)。&& 和 || 具有短路求值特性。
3.5.4 位运算符
&(与)、|(或)、^(异或/按位取反)、<<(左移)、>>(右移)、&^(位清除)。
a, b := 12, 10
fmt.Println(a & b) // 8
fmt.Println(a | b) // 14
fmt.Println(a ^ b) // 6
fmt.Println(a << 1) // 24
Go 没有
++a或a++作为表达式,a++和a--只能作为独立语句使用,且没有前置形式。
3.6 类型转换
Go 是强类型语言,不存在隐式类型转换,所有类型转换都必须显式进行:
var i int = 100
var f float64 = float64(i) // int -> float64
var u uint = uint(f) // float64 -> uint
// 字符串与数字之间需要使用 strconv 包,不能直接转换
import "strconv"
s := strconv.Itoa(100) // int -> string "100"
n, err := strconv.Atoi("100") // string -> int
常见误区:
string(65)不会得到"65",而是得到字符"A"(码点 65 对应的字符)。字符串与数字的转换必须使用strconv包。
3.7 fmt 格式化输出
fmt 包是最常用的输出工具,常用动词如下:
| 动词 | 含义 |
|---|---|
%v |
默认格式输出值 |
%+v |
输出结构体时带字段名 |
%#v |
Go 语法表示 |
%T |
输出值的类型 |
%d |
十进制整数 |
%f |
浮点数 |
%s |
字符串 |
%q |
带引号的字符串 |
%t |
布尔值 |
%p |
指针地址 |
%x |
十六进制 |
name, age := "Go", 15
fmt.Printf("%s 已经 %d 岁了\n", name, age)
fmt.Printf("类型: %T, 值: %v\n", age, age)
3.8 本章小结
本章覆盖了 Go 的基础语法核心:变量与常量声明、iota 枚举、基本数据类型(整型、浮点、字符串、byte/rune)、运算符以及显式类型转换。Go 强调简洁与显式——未使用的变量和导入会报错,没有隐式类型转换,这些设计使代码更安全、更易读。
下一章我们将学习流程控制语句与函数。