Go 语言核心语法手册

单页速查:从包与类型到接口、泛型、并发与错误处理。代码示例需在函数体内或独立文件中运行;配合 go.dev 文档 动手验证。

1. 包(package)与导入(import)

每个源文件以 package 名称 开头;可执行程序入口包名为 main

标准形式

package main

import (
    "fmt"
    "strings"
)

点导入、别名、空白导入

. 将包符号导入当前命名空间(少用)。_ 仅执行包的 init,用于副作用(如驱动注册)。

import . "fmt"           // 可直接 Println
import bar "path/to/foo" // 用 bar 访问
import _ "image/png"     // 注册 PNG 解码器

2. 标识符、关键字与可见性

命名规则

字母、数字、下划线;不能以数字开头。25 个关键字不可作标识符:break case chan const continue default defer else fallthrough for func go goto if import interface map package range return select struct switch type var

导出(可见性)

首字母大写的标识符对包外可见;小写为包内私有。

type User struct { Name string; age int } // Name 导出,age 不导出

空白标识符 _

丢弃不需要的返回值或导入副作用。

_, err := os.Open("a.txt")
for _, v := range slice { _ = v }

3. 常量(const)与 iota

常量声明

常量必须是编译期可确定值;可成组声明。

const Pi = 3.14
const (
    StatusOK    = 200
    StatusNotFound = 404
)

iota 计数器

const ( ) 块中从 0 递增,每行 +1;可配合表达式。

const (
    _ = iota           // 0,丢弃
    KB = 1 << (10 * iota) // 1 << 10
    MB
    GB
)

4. 变量(var)与短变量声明(:=)

var 多种形式

var x int
var y, z = 1, "hi"
var a, b int = 1, 2
var p = &x

短声明 :=

仅在函数内使用;左侧至少有一个新变量名时,可对已有变量重新赋值混合声明。

func f() {
    i := 0
    j, k := 1, 2
    i, m := 3, 4 // i 重赋值,m 新声明
    _ = j; _ = k; _ = m
}

5. 预定义类型与复合类型字面量

布尔与数值

boolint int8 int16 int32 int64uint uint8(即 byte) uint16 uint32 uint64 uintptrfloat32 float64complex64 complex128

rune 与 string

runeint32 别名,表示 Unicode 码点。

复合类型关键字

array slice struct map chan func interface 等由类型构造符组成。

6. 零值、类型转换与比较

零值

未显式初始化时:数值 0、bool false、指针/nil 接口/slice/map/channel 为 nil,string 为 ""

显式类型转换

Go 无隐式数值转换(除常量与部分无类型常量上下文)。

var u uint = uint(i)
f := float64(3)

可比较类型

== != 适用于布尔、数值、字符串、指针、channel、接口(动态类型可比)、struct(字段均可比)、array(元素可比)。slice、map、函数类型不可比较(可与 nil 比)。

7. 运算符

算术与位运算

+ - * / %;整数 & | ^ &^ << >>;一元 + - ! ^ * & <-(接收)。

逻辑与比较

&& || !== != < <= > >=

寻址与解引用

x := 1
p := &x
*p = 2

8. 字符串与字符

字面量与 raw string

s := "行\n换行"
raw := `C:\path\file` // 反引号内不转义

不可变与字节/rune

string 只读字节序列;修改需转为 []byte[]rune

b := []byte(s)
r := []rune(s)

9. 数组(array)

长度是类型的一部分:[4]int[5]int 不同类型。

var a [3]int
a[0] = 1
b := [...]int{1, 2, 3} // 长度由初始化推导

10. 切片(slice)

声明与字面量

var s []int
s = []int{1, 2, 3}
s = make([]int, 3, 8) // len=3 cap=8

切片表达式与共享底层数组

low, high, max := 1, 3, 5
sub := base[low:high]       // 容量到 base 末尾
sub2 := base[low:high:max]  // 三索引,容量 max-low

append 与 copy

s = append(s, 4, 5)
n := copy(dst, src)

11. 映射(map)

var m map[string]int // nil,不能写入
m = make(map[string]int)
m["a"] = 1
delete(m, "a")
v, ok := m["a"] // 逗号 ok 判断键是否存在

12. 指针(pointer)

Go 无指针运算(除 unsafe);不能得到任意临时值的地址(部分例外如复合字面量取址规则)。

type T struct{ X int }
p := &T{X: 1}
p.X = 2 // 隐式解引用

13. 结构体(struct)、匿名字段与标签

定义与字面量

type Point struct {
    X, Y float64
}
p := Point{X: 1, Y: 2}
q := Point{3, 4} // 按字段顺序,需完整或全用键名

嵌入(embedding)

匿名字段提升字段与方法,类似“组合”。

type Inner struct { A int }
type Outer struct {
    Inner // 嵌入
    B int
}
var o Outer
o.A = 1 // 提升自 Inner

结构体标签(tag)

type User struct {
    Name string `json:"name" xml:"Name"`
}

14. 方法(method)

值接收者与指针接收者

指针接收者可修改接收者、避免大结构体拷贝;值接收者操作副本。

func (p Point) Dist() float64 { return p.X * p.X }
func (p *Point) Move(dx, dy float64) {
    p.X += dx; p.Y += dy
}

15. 接口(interface)

接口类型与实现

实现是隐式的:类型方法集包含接口所需全部方法即满足接口。

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
}

空接口与类型断言

var any interface{} = 42
// Go 1.18+ 可用 any 代替 interface{}
v := any.(int)       // 失败则 panic
w, ok := any.(int)   // ok 为 false 安全

类型开关 type switch

switch t := any.(type) {
case int:
    _ = t
case string:
    _ = t
default:
}

16. 函数(func)

声明、多返回值、命名返回值

func Div(a, b int) (q int, r int, err error) {
    if b == 0 {
        err = fmt.Errorf("zero divisor")
        return // 裸 return,返回命名零值
    }
    q, r = a/b, a%b
    return
}

可变参数

func Sum(nums ...int) int {
    s := 0
    for _, n := range nums { s += n }
    return s
}

函数类型与匿名函数

type Handler func(int) int
var fn Handler = func(x int) int { return x + 1 }

17. defer

defer 语句推迟到外层函数返回前执行;参数在 defer 语句处立即求值。多个 defer 后进先出(栈)。

func read() error {
    f, err := os.Open("f.txt")
    if err != nil { return err }
    defer f.Close()
    // ...
    return nil
}

18. 控制流:if、for、switch、select、goto

if 可带短声明

if err := run(); err != nil {
    return err
} else {
    // else 块内 err 仍可见
}

for:唯一循环关键字

for i := 0; i < 10; i++ { }
for cond { }           // 等同 while
for { }                // 死循环
for k, v := range m { }

switch 与 fallthrough

switch x := v.(type) { // v 须为接口类型值
case int:
    fallthrough // 继续执行下一 case 体(不重新判断)
case int64:
default:
    _ = x
}

select:多路 channel

select {
case v := <-ch1:
    _ = v
case ch2 <- x:
default:
}

break / continue 与标签

Outer:
    for i := 0; i < 3; i++ {
        for j := 0; j < 3; j++ {
            break Outer
        }
    }

goto(受限跳转)

不能跳入块内越过变量声明等;实际少用。

19. range 详解

// slice/array: 索引, 值副本
for i, v := range s { _ = i; _ = v }
// map: 键, 值
for k, v := range m { _ = k; _ = v }
// string: 索引(byte 偏移), rune(码点值)
for i, r := range "你好" { _ = i; _ = r }
// channel: 接收直到关闭
for v := range ch { _ = v }

20. make 与 new

new(T)

分配内存,置零值,返回 *T。用于值类型指针。

p := new(int)
*p = 7

make

仅用于 slicemapchan,返回已初始化(非 nil)的引用类型值。

s := make([]int, 0, 10)
m := make(map[string]int)
c := make(chan int, 2)

21. 泛型(Go 1.18+)

类型参数与约束

// import "constraints"
func Min[T constraints.Ordered](a, b T) T {
    if a < b { return a }
    return b
}

type Vector[T any] struct { data []T }

接口约束、并集、~ 底层类型

type Signed interface {
    ~int | ~int8 | ~int16 | ~int32 | ~int64
}

type MyInt int
func F[T Signed](x T) {} // MyInt 底层为 int 可满足 ~int

comparable 预声明约束

func Keys[K comparable, V any](m map[K]V) []K {
    out := make([]K, 0, len(m))
    for k := range m { out = append(out, k) }
    return out
}

22. 类型定义(type)与类型别名

定义新命名类型

type ID uint64
type ErrFunc func() error

类型别名(与原名完全同一类型)

// 与右侧为同一类型,可互换赋值
type IntList = []int
type Handler = func() error

23. 复合字面量、取址与可变参数展开

结构体、数组、切片、map、channel 字面量

p := &Point{X: 1, Y: 2} // T{...} 取址,堆或栈由编译器决定
m := map[string]int{"a": 1}
s := []int{1, 2, 3}
a := [...]int{1, 2} // 数组长度由初始化推导

调用时将切片展开为多个参数

func Sum(nums ...int) int { /* ... */ return 0 }
vals := []int{1, 2, 3}
Sum(vals...) // 等价 Sum(1,2,3),切片须与 ...T 元素类型一致

24. 并发:goroutine、channel、sync 要点

go 语句

go func() { fmt.Println("async") }()

channel:创建、方向、缓冲

ch := make(chan int)       // 无缓冲,同步握手
buf := make(chan int, 10)   // 缓冲

var sendOnly chan<- int = ch
var recvOnly <-chan int = ch

关闭与 range

close(ch)
for v := range ch { _ = v }

同步原语(语法级常用配合)

sync.Mutex RWMutex WaitGroup Once sync/atomic 等用于共享内存同步;与 channel 可按场景选择。

25. 错误(error)处理惯用法

error 接口

type error interface {
    Error() string
}

构造与包装(Go 1.13+)

err := errors.New("plain")
err = fmt.Errorf("wrap: %w", err)
if errors.Is(err, os.ErrNotExist) { }
var pathErr *fs.PathError
if errors.As(err, &pathErr) { }

26. panic 与 recover

panic 停止当前 goroutine 正常执行,展开 defer;recover() 仅在 defer 内调用可捕获 panic 值。常规错误用 error 返回,不用 panic 控制流。

defer func() {
    if r := recover(); r != nil {
        fmt.Println("recovered:", r)
    }
}()
panic("oops")

27. init 函数

每个包可有多个 func init(),在 main 之前、按依赖顺序自动调用;不可被引用,无参数无返回值。

func init() {
    // 包级初始化
}