Appearance
Go 速记表
基础语法
Hello World
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
输入输出
package main
import "fmt"
func main() {
// 输出
fmt.Println("Hello, World!")
fmt.Printf("Name: %s, Age: %d\n", "Alice", 25)
// 输入
var name string
var age int
fmt.Print("Enter your name: ")
fmt.Scanln(&name)
fmt.Print("Enter your age: ")
fmt.Scanln(&age)
fmt.Printf("Hello, %s!\n", name)
}
注释
// 单行注释
/* 多行注释
可以换行 */
// Package 文档注释
// 紧贴 package 声明上方
变量与常量
声明方式
var name string = "Alice"
var age int = 25
var x int // 零值初始化
// 短声明(仅函数内)
count := 10
name := "Bob"
// 多变量声明
var (
x int = 1
y int = 2
)
a, b := 1, 2
常量
const PI = 3.14
const (
StatusOK = 200
StatusNotFound = 404
)
// iota 枚举
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
)
作用域
var globalVar = "global" // 包级作用域
func example() {
localVar := "local" // 函数作用域
if true {
blockVar := "block" // 块作用域
}
}
数据类型
基本类型
// 整数
int int8 int16 int32 int64
uint uint8 uint16 uint32 uint64 uintptr
// 浮点数
float32 float64
// 复数
complex64 complex128
// 其他
bool
byte // uint8 别名
rune // int32 别名,表示 Unicode 码点
string
复合类型
// 数组
var arr [5]int
// 切片
var slice []int
// 映射
var m map[string]int
// 结构体
type Person struct {
Name string
Age int
}
// 指针
var p *int
类型转换
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
// 字符串转换
str := strconv.Itoa(i)
num, err := strconv.Atoi(str)
f, err := strconv.ParseFloat("3.14", 64)
零值
// 未初始化变量的默认值
0 // 数字类型
false // bool
"" // string
nil // 指针、切片、映射、通道、函数
运算符
算术运算符
+ - * / %
++ -- // 只能后置
比较运算符
== !=
> < >= <=
逻辑运算符
&& || !
位运算符
& | ^ &^ // 与、或、异或、与非
<< >> // 左移、右移
赋值运算符
= += -= *= /= %=
&= |= ^= <<= >>= &^=
取址与解引用
&x // 取地址
*p // 解引用
字符串
字符串基础
s := "hello"
s := `multi
line
string` // 原始字符串
// 字符串不可变
// s[0] = 'H' // 错误
len(s) // 字节长度
字符串操作
import "strings"
strings.Contains(s, "sub")
strings.HasPrefix(s, "pre")
strings.HasSuffix(s, "suf")
strings.Index(s, "sub")
strings.LastIndex(s, "sub")
strings.Count(s, "sub")
strings.ToUpper(s)
strings.ToLower(s)
strings.Title(s)
strings.TrimSpace(s)
strings.Trim(s, "cutset")
strings.TrimLeft(s, "cutset")
strings.TrimRight(s, "cutset")
字符串分割与拼接
parts := strings.Split(s, " ")
joined := strings.Join(parts, "-")
repeated := strings.Repeat("ab", 3)
strings.Replace(s, "old", "new", n)
strings.ReplaceAll(s, "old", "new")
字符串构建
import "strings"
var sb strings.Builder
sb.WriteString("Hello")
sb.WriteString(" World")
result := sb.String()
// 格式化
s := fmt.Sprintf("Name: %s, Age: %d", name, age)
集合数据结构
数组
var arr [5]int
arr := [5]int{1, 2, 3, 4, 5}
arr := [...]int{1, 2, 3} // 自动推导长度
len(arr) // 长度
// 遍历
for i, v := range arr {
fmt.Println(i, v)
}
切片
// 创建切片
s := []int{1, 2, 3}
s := make([]int, 5) // 长度 5
s := make([]int, 0, 10) // 长度 0,容量 10
// 操作
s = append(s, 4)
s = append(s, 5, 6, 7)
s = append(s, other...)
len(s) // 长度
cap(s) // 容量
// 切片操作
sub := s[1:3] // [1, 3)
sub := s[:3] // 前 3 个
sub := s[2:] // 从索引 2 到末尾
映射 (Map)
// 创建
m := make(map[string]int)
m := map[string]int{
"alice": 25,
"bob": 30,
}
// 操作
m["key"] = 100
value := m["key"]
// 检查键是否存在
value, ok := m["key"]
if ok {
fmt.Println(value)
}
delete(m, "key")
len(m)
// 遍历
for key, value := range m {
fmt.Println(key, value)
}
控制流
if / else
if condition {
// 执行
} else if other {
// 执行
} else {
// 执行
}
// if 带初始化语句
if err := doSomething(); err != nil {
return err
}
switch
switch value {
case 1:
fmt.Println("one")
case 2, 3:
fmt.Println("two or three")
default:
fmt.Println("other")
}
// 无条件 switch
switch {
case x < 0:
fmt.Println("negative")
case x == 0:
fmt.Println("zero")
default:
fmt.Println("positive")
}
for 循环
// C 风格 for
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// while 风格
for condition {
// 执行
}
// 无限循环
for {
// 执行
if done {
break
}
}
// range 遍历
for i, v := range slice {
fmt.Println(i, v)
}
// 只要值
for _, v := range slice {
fmt.Println(v)
}
跳转语句
break // 退出循环
continue // 跳过本次
return // 返回
// 标签跳转
outer:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
break outer
}
}
}
defer
func example() {
defer fmt.Println("World") // 函数返回前执行
fmt.Println("Hello")
// 输出:Hello World
}
// 常用于资源清理
file, err := os.Open("file.txt")
defer file.Close()
函数
函数定义
func add(a, b int) int {
return a + b
}
// 多返回值
func swap(a, b string) (string, string) {
return b, a
}
// 命名返回值
func divide(a, b int) (result int, err error) {
if b == 0 {
err = errors.New("division by zero")
return
}
result = a / b
return
}
可变参数
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}
result := sum(1, 2, 3, 4, 5)
匿名函数与闭包
// 匿名函数
fn := func(x int) int {
return x * 2
}
// 立即执行
result := func(x int) int {
return x * 2
}(5)
// 闭包
func counter() func() int {
count := 0
return func() int {
count++
return count
}
}
高阶函数
func apply(fn func(int) int, value int) int {
return fn(value)
}
func multiplier(factor int) func(int) int {
return func(x int) int {
return x * factor
}
}
结构体与方法
结构体定义
type Person struct {
Name string
Age int
}
// 创建实例
p1 := Person{Name: "Alice", Age: 25}
p2 := Person{"Bob", 30}
p3 := &Person{Name: "Charlie"}
方法
func (p Person) Greet() string {
return "Hello, I'm " + p.Name
}
// 指针接收者(可修改)
func (p *Person) HaveBirthday() {
p.Age++
}
p := Person{Name: "Alice", Age: 25}
p.HaveBirthday()
嵌入(组合)
type Address struct {
City string
Country string
}
type Employee struct {
Person // 嵌入
Address // 嵌入
Salary int
}
e := Employee{
Person: Person{Name: "Alice", Age: 25},
Salary: 5000,
}
fmt.Println(e.Name) // 直接访问嵌入字段
接口
接口定义
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 组合接口
type ReadWriter interface {
Reader
Writer
}
实现接口
type MyReader struct{}
func (r MyReader) Read(p []byte) (n int, err error) {
// 实现细节
return len(p), nil
}
// 隐式实现,无需声明
var r Reader = MyReader{}
空接口
// interface{} 或 any (Go 1.18+) 可以表示任何类型
var i interface{} = "hello"
var a any = 42
类型断言
var i interface{} = "hello"
// 类型断言
s := i.(string)
// 安全断言
s, ok := i.(string)
if ok {
fmt.Println(s)
}
// 类型判断
switch v := i.(type) {
case int:
fmt.Printf("int: %d\n", v)
case string:
fmt.Printf("string: %s\n", v)
default:
fmt.Printf("unknown\n")
}
错误处理
错误处理模式
result, err := someFunction()
if err != nil {
return err // 或 log.Fatal(err)
}
// 使用 errors 包
import "errors"
err := errors.New("something went wrong")
err := fmt.Errorf("error: %s", msg)
自定义错误
type MyError struct {
Code int
Message string
}
func (e *MyError) Error() string {
return fmt.Sprintf("error %d: %s", e.Code, e.Message)
}
err := &MyError{Code: 404, Message: "Not Found"}
错误包装
Go 1.13+
import "errors"
err := fmt.Errorf("failed to process: %w", originalErr)
// 检查错误
if errors.Is(err, os.ErrNotExist) {
// 处理
}
// 类型判断
var pathErr *os.PathError
if errors.As(err, &pathErr) {
fmt.Println(pathErr.Path)
}
panic 与 recover
// panic 导致程序崩溃
panic("something went wrong")
// recover 捕获 panic
func safeDivide(a, b int) (result int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
result = 0
}
}()
result = a / b
return
}
并发编程
Goroutine
// 启动 goroutine
go func() {
fmt.Println("Running in goroutine")
}()
go processData(data)
// 匿名 goroutine
go func(msg string) {
fmt.Println(msg)
}("Hello")
Channel
// 创建 channel
ch := make(chan int)
ch := make(chan int, 10) // 带缓冲
// 发送
ch <- 42
// 接收
value := <-ch
// 关闭
close(ch)
// 检查 channel 是否关闭
value, ok := <-ch
if !ok {
fmt.Println("Channel closed")
}
Select
select {
case msg := <-ch1:
fmt.Println("Received from ch1:", msg)
case msg := <-ch2:
fmt.Println("Received from ch2:", msg)
case <-time.After(time.Second):
fmt.Println("Timeout")
default:
fmt.Println("No communication")
}
WaitGroup
import "sync"
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
fmt.Println("Worker", id)
}(i)
}
wg.Wait()
Mutex
import "sync"
var mu sync.Mutex
var counter int
mu.Lock()
counter++
mu.Unlock()
// RWMutex
var rwMu sync.RWMutex
rwMu.RLock() // 读锁
rwMu.RUnlock()
rwMu.Lock() // 写锁
rwMu.Unlock()
文件操作
读取文件
import "os"
// 读取全部
data, err := os.ReadFile("file.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// 逐行读取
file, err := os.Open("file.txt")
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
写入文件
// 写入全部
err := os.WriteFile("file.txt", []byte("content"), 0644)
// 追加写入
file, err := os.OpenFile("file.txt", os.O_APPEND|os.O_WRONLY, 0644)
defer file.Close()
file.WriteString("more content\n")
JSON 操作
import "encoding/json"
// 序列化
data, err := json.Marshal(obj)
jsonStr, err := json.MarshalIndent(obj, "", " ")
// 反序列化
var obj MyStruct
err := json.Unmarshal(data, &obj)
泛型
泛型函数
Go 1.18+
func Min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}
result := Min(1, 2)
result := Min("a", "b")
泛型类型
type Stack[T any] struct {
items []T
}
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
func (s *Stack[T]) Pop() T {
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item
}
最佳实践
代码风格
// 使用 gofmt 格式化代码
// 使用短变量声明
x := 10
// 尽早返回
if err != nil {
return err
}
// 使用有意义的名称
count := len(users) // 好
c := len(users) // 不好
错误处理
// 不要忽略错误
result, err := someFunc()
if err != nil {
return fmt.Errorf("failed to do something: %w", err)
}
// 使用 defer 清理资源
file, err := os.Open("file.txt")
if err != nil {
return err
}
defer file.Close()
并发安全
// 不要通过共享内存通信,而要通过通信共享内存
// 使用 channel 传递数据
ch := make(chan int)
go func() {
ch <- processData()
}()
result := <-ch
// 必要时使用 mutex
var mu sync.Mutex
mu.Lock()
// 访问共享资源
mu.Unlock()
工具链
Go 命令
go run main.go # 运行
go build # 编译
go test # 测试
go mod init # 初始化模块
go mod tidy # 整理依赖
go get package # 获取包
go install # 安装
go fmt # 格式化
go vet # 静态分析
测试
// example_test.go
package example
import "testing"
func TestAdd(t *testing.T) {
result := Add(2, 3)
if result != 5 {
t.Errorf("Expected 5, got %d", result)
}
}
// 基准测试
func BenchmarkAdd(b *testing.B) {
for i := 0; i < b.N; i++ {
Add(2, 3)
}
}
常用工具
# golangci-lint - 代码检查
golangci-lint run
# go-staticcheck - 静态分析
staticcheck ./...
# godoc - 文档生成
godoc -http=:6060