Go 语言语法完全指南
前言
Go,也称 Golang,Google 推出的一门静态强类型、编译型语言。特点:语法简介、编译快、并发能力强、工程化支持完善。应用领域如:后端开发、云原生、微服务、分布式系统、DevOps 工具链等。
本文是我学习 Golang 后,以系统性总结的方式对其语法知识进行完整梳理,作为后续 go 开发时参考笔记,也可作为:
- Go 初学者系统入门笔记
- Go 语法速查手册
- 编写 Go 项目时基础知识参考
目录
- 1. Go 语言简介
- 2. Go 程序基本结构
- 3. 基础语法
- 4. 流程控制
- 5. 复合数据类型
- 6. 指针
- 7. 函数
- 8. 结构体
- 9. 方法
- 10. 接口
- 11. 错误处理
- 12. 并发编程
- 13. 泛型(Go 1.18+)
- 14. 文件与 I/O 操作
- 15. 反射(Reflection)
- 16. 常用标准库概览
- 17. 测试
- 18. 包、模块与工程化管理
- 19. Go 常见易错点总结
- 20. 编码规范与最佳实践
1. Go 语言简介
1.1 语言特点
- 语法简介: Go 语法简洁。借鉴了 C 语言的风格,但去掉了许多复杂的特性。
- 编译型语言:编译速度极快,生成单一二进制文件。
- 天生并发:内置 goroutine 和 channel 简化并发编程。
- 垃圾回收:无需手动管理内存。
- 静态类型 + 类型推断:既有静态类型的安全性,又有类型推断的便利性。
- 标准库丰富:网络、文件、编码、加密、测试等开箱即用
- 工程化能力强:内置格式化、测试、模块管理工具。
- 跨平台:支持多种操作系统和架构,这没啥好说的市面上大部分语言都支持。
1.2 应用场景
- Web 后端开发
- API 服务开发
- 云原生与容器生态
- 微服务架构
- 网络编程
- 运维工具和命令行工具
- 分布式系统
1.3 环境搭建
# 下载安装:https://go.dev/dl/ |
# 验证安装 |
go version |
# 如果安装成功,会输出类似信息: |
go version go1.22.0 windows/amd64 |
1.4 Hello World
创建文件main.go,内容如下:
package main |
import "fmt" |
func main() { |
fmt.Println("Hello, World!") |
} |
go run main.go # 直接运行 |
go build main.go # 编译生成二进制 |
2. Go 程序基本结构
Go 程序通常由以下几个部分组成:
- 包声明
- 导入包
- 全局声明
- 函数定义
- main 函数
2.1 package
每个 Go 文件都必须以package开头,用于声明该文件属于哪个包。
package main |
如果一个程序要作为可执行程序运行,则必须使用main包。
2.2 import
使用import导入依赖包。
import "fmt" |
如果导入多个包,可以使用圆括号:
import ( |
"fmt" |
"time" |
) |
2.3 main 函数
Go 程序的入口是main包中的main()函数。
func main() { |
fmt.Println("程序开始执行") |
} |
2.4 注释
Go 支持两种注释方式:
单行注释
// 这是单行注释 |
多行注释
/* |
这是多行注释 |
可以写多行内容 |
*/ |
2.5 标识符命名规则
标识符包括变量名、函数名、类型名等,命名规则如下:
- 由字母、数字、下划线组成
- 不能以数字开头
- 区分大小写
- 不能与关键字重名
例如:
var name string |
var userAge int |
var _temp int |
2.6 可见性规则
Go 使用首字母大小写控制访问权限:
- 首字母大写:可被包外访问
- 首字母小写:仅包内可访问
例如:
type User struct { |
Name string |
age int |
} |
其中:
Name可导出age不可导出
3. 基础语法
3.1 变量
// 显式声明 |
var name string = "Go" |
var age int // 零值:0 |
// 类型推断 |
var score = 100 |
// 短变量声明(只能在函数内部使用) |
lang := "Golang" |
// 批量声明 |
var a, b, c int |
var x, y = 10, 20 |
// 也可以分组声明: |
var ( |
name string = "Alice" |
age int = 20 |
city string = "Beijing" |
gender bool // 零值:false |
) |
// Go 使用 `_` 表示匿名变量,用于忽略某个值,常见于函数多返回值场景。 |
n, _ := 10, 20 |
fmt.Println(n) |
零值规则:Go 中变量声明后自动初始化为零值。
| 类型 | 零值 |
|---|---|
| int/float | 0 |
| string | "" |
| bool | false |
| 指针/切片/map/channel/接口/函数 | nil |
3.2 常量
const Pi = 3.14159 |
const ( |
StatusOK = 200 |
StatusNotFound = 404 |
) |
// iota:常量生成器,从 0 开始自增 |
const ( |
Sunday = iota // 0 |
Monday // 1 |
Tuesday // 2 |
) |
// iota 高级用法 |
const ( |
_ = iota // 0 丢弃 |
KB = 1 << (10 * iota) // 1 << 10 = 1024 |
MB // 1 << 20 |
GB // 1 << 30 |
) |
3.3 基本数据类型
示例:
// 整型,对应的无符号整型:- uint uint8 uint16 uint32 uint64 |
var a int // 平台相关:32 或 64 位 |
var b int8 // -128 ~ 127 |
var c int16 |
var d int32 // 别名 rune(表示 Unicode 码点) |
var e int64 |
var f uint8 // 别名 byte(0 ~ 255) |
// 浮点 |
var g float32 |
var h float64 // 默认浮点字面量类型 |
// 复数 |
var i complex64 |
var j complex128 |
// 布尔 |
var k bool // 布尔类型只有两个值:true 和 false,注意:Go 中不能将整数直接当作布尔值使用。 |
// 字符串(Go 中字符串本质上是**只读字节序列**) |
var s string = "hello" |
// rune 与 byte,字节与字符 |
var r rune = '中' // int32 别名,Unicode 码点 |
var by byte = 'A' // uint8 别名 |
常见转义字符:
\n换行\t制表符\"双引号\\反斜杠\r回车\b退格\0空字符
原始字符串:
使用反引号 `` 定义原始字符串,保留原始格式:
str := `这是一个原始字符串 |
不会处理转义字符 \n |
可以换行` |
3.4 类型转换
Go没有隐式类型转换,必须显式转换:
var i int = 42 |
var f float64 = float64(i) |
var u uint = uint(f) |
var x float64 = 3.14 |
var y int = int(x) // 注意:浮点转整数会截断小数部分,y 的值为 3 |
// 字符串 <-> 数字 需要用 strconv |
s := strconv.Itoa(42) // int -> string: "42" |
n, _ := strconv.Atoi("42") // string -> int: 42 |
// 字符串 <-> 字节切片 |
bs := []byte("hello") |
s2 := string(bs) |
3.5 自定义类型与类型别名
// 自定义类型(全新类型,可以添加方法) |
type Celsius float64 |
type Handler func(string) error |
type MyInt int |
var a MyInt = 10 |
// MyInt 是 int 的新类型,不能直接赋值 |
var b int = a // ❌ 编译错误 |
var c int = int(a) // ✅ 需要显式转换 |
// 类型别名(完全等同于原类型) |
type Byte = uint8 |
type Rune = int32 |
var x Byte = 255 |
var y uint8 = x // ✅ Byte 是 uint8 的别名,可以直接赋值 |
var z Rune = 'A' |
z = 300 // ✅ Rune 是 int32 的别名,可以直接赋值 |
