Go 语言基础入门:从零到实战,一篇文章掌握核心语法

适合刚接触 Go 语言的同学,涵盖基础数据类型、流程控制、数组切片、字典、结构体、方法等,并附有 4 个必做练习。


1. 前言

最近我开始学习 Go 语言,经过一天的系统梳理和实战练习,把最基础的知识点过了一遍。Go 是一门静态强类型、编译型、并发支持良好的语言,语法简洁,特别适合后端开发、云原生和中间件编写。

这篇文章将按照我学习的主线,总结 Go 的核心语法,并提供 4 个练习题(成绩统计、字符计数、数字金字塔、图书管理),最后附上完整代码思路。如果你也在入门阶段,希望这篇文章对你有帮助。


2. 基础数据类型

Go 的基本类型包括:

go

复制代码
bool                     // true / false
string                   // 字符串,UTF-8
int  int8  int16  int32  int64
uint uint8 uint16 uint32 uint64
byte                     // uint8 别名
rune                     // int32 别名,表示 Unicode 码点
float32 float64
complex64 complex128

重点:rune 处理中文等 Unicode 字符,byte 处理 ASCII。

变量声明可以用 var name type 或短变量 :=

go

复制代码
var age int = 18
name := "Alice"
var isOk bool

3. 输入与输出

  • 输出fmt.Print / fmt.Printf / fmt.Println

  • 输入fmt.Scan / fmt.Scanf / fmt.Scanln

go

复制代码
var x int
fmt.Print("请输入数字:")
fmt.Scan(&x)
fmt.Printf("你输入的是:%d\n", x)

4. 运算符

分类 运算符
算术 + - * / % ++ --
比较 == != < > <= >=
逻辑 `&&
位运算 `&
赋值 = += -= *= /= %= ...

注意++-- 只能独立使用,不能作为表达式(c = a++ 是错误的)。


5. 流程控制

5.1 if

go

复制代码
if score >= 90 {
    fmt.Println("优秀")
} else if score >= 60 {
    fmt.Println("及格")
} else {
    fmt.Println("不及格")
}

支持在条件前加简单语句,作用域仅限于 if 块。

5.2 switch

go

复制代码
switch day {
case 1, 3, 5:
    fmt.Println("奇数日")
case 2, 4, 6:
    fmt.Println("偶数日")
default:
    fmt.Println("周日")
}

不需要 break,默认自动终止。如需穿透,使用 fallthrough

5.3 for 循环

Go 只有 for,没有 while

go

复制代码
// 经典 for
for i := 0; i < 10; i++ {}

// while 形式
sum := 1
for sum < 100 {
    sum += sum
}

// 无限循环
for {
    break
}

5.4 range 遍历

go

复制代码
nums := []int{2,4,6}
for i, v := range nums {
    fmt.Println(i, v)
}

m := map[string]int{"a":1, "b":2}
for k, v := range m {
    fmt.Println(k, v)
}

for _, ch := range "Go语言" {
    fmt.Printf("%c ", ch)   // G o 语 言
}

6. 指针

  • *T 表示指向 T 的指针,零值为 nil

  • & 取地址,* 解引用。

  • 没有指针运算 (不能 p++)。

go

复制代码
func setZero(x *int) {
    *x = 0
}
a := 10
setZero(&a)
fmt.Println(a) // 0

7. 数组和切片

7.1 数组(固定长度,值类型)

go

复制代码
var arr [3]int = [3]int{1,2,3}
arr2 := [...]int{4,5,6}   // 由编译器确定长度

7.2 切片(动态数组,引用类型)

go

复制代码
// 创建
s1 := []int{1,2,3}
s2 := make([]int, 5, 10)  // 长度5,容量10

// 追加
s1 = append(s1, 4, 5)

// 切片操作
sub := s1[1:3]   // [2,3]

// 复制
copy(dest, src)

8. 字典(map)

必须初始化才能使用,零值为 nil,直接赋值会 panic。

go

复制代码
// 正确初始化
m := make(map[string]int)
m["age"] = 18

// 字面量
m2 := map[string]string{
    "name": "Tom",
}

// 读取、判断存在
v, ok := m["age"]
if ok {
    fmt.Println(v)
}

// 删除
delete(m, "age")

练习应用:统计字符串中每个字符出现次数。


9. 内置函数

常用内置函数一览:

函数 作用
len(v) 长度
cap(v) 容量
make(T, args) 创建切片/map/通道
new(T) 返回 *T 零值指针
append(s, elems) 追加到切片
copy(dst, src) 复制切片
delete(m, k) 删除 map 元素
close(ch) 关闭通道
panic / recover 异常处理

10. 结构体

结构体是字段的集合,可以定义方法。

go

复制代码
type Book struct {
    Title  string
    Author string
    Price  float64
}

func (b Book) ShowInfo() {
    fmt.Printf("《%s》作者:%s 价格:%.2f\n", b.Title, b.Author, b.Price)
}

func (b *Book) SetPrice(p float64) {
    b.Price = p
}

func main() {
    book := Book{
        Title:  "Go语言实战",
        Author: "William Kennedy",
        Price:  89.0,
    }
    book.ShowInfo()
    book.SetPrice(79.0)
}

方法接收者:值接收者不修改原对象,指针接收者可修改。


11. 函数与方法

  • 函数 :支持多返回值、可变参数、匿名函数、闭包、defer

go

复制代码
func div(a, b int) (int, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}
  • 方法:与特定类型绑定的函数。

12. 实战练习(附代码思路)

练习1:学生成绩统计

随机生成10个0~100的成绩,计算平均分、最高分、最低分、及格人数以及各分数段人数。

核心代码

go

复制代码
// 单次循环完成所有统计
for _, score := range scores {
    sum += score
    // 最值
    if score > max { max = score }
    if score < min { min = score }
    // 及格
    if score >= 60 { passCount++ }
    // 分段
    switch {
    case score >= 90: excellent++
    case score >= 80: good++
    case score >= 70: medium++
    case score >= 60: pass++
    default: fail++
    }
}
avg := float64(sum) / float64(len(scores))

收获 :掌握了切片遍历、switch 顺序匹配、类型转换。


练习2:字符出现次数统计

输入 "zcddaa",输出 a:2 c:1 d:2 z:1(按字母顺序)。

go

复制代码
func countAndPrint(s string) {
    counts := make(map[rune]int)
    for _, ch := range s {
        counts[ch]++
    }
    // 提取键并排序
    keys := make([]rune, 0, len(counts))
    for k := range counts {
        keys = append(keys, k)
    }
    sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
    for i, k := range keys {
        if i > 0 {
            fmt.Print(" ")
        }
        fmt.Printf("%c:%d", k, counts[k])
    }
}

收获map + sort.Slice,理解 rune 和排序。


练习3:数字金字塔

随机生成 1~10 层,打印如下图形(n=5):

text

复制代码
    1
   121
  12321
 1234321
123454321

代码

go

复制代码
for i := 1; i <= n; i++ {
    // 空格
    for j := 0; j < n-i; j++ {
        fmt.Print(" ")
    }
    // 递增
    for j := 1; j <= i; j++ {
        fmt.Print(j)
    }
    // 递减
    for j := i - 1; j >= 1; j-- {
        fmt.Print(j)
    }
    fmt.Println()
}

收获:嵌套循环、找规律。


练习4:图书管理系统

定义 Book 结构体,创建 3 本书的切片,实现:

  • 计算总价的方法

  • 找出最贵的书

  • 按价格从高到低排序输出

代码片段

go

复制代码
type Book struct {
    Title  string
    Author string
    Price  float64
}

type BookList []Book

func (bl BookList) Total() float64 {
    var sum float64
    for _, b := range bl {
        sum += b.Price
    }
    return sum
}

func main() {
    books := BookList{
        {"Go实战", "Kennedy", 89.0},
        {"CSAPP", "Bryant", 129.0},
        {"算法图解", "Bhargava", 59.5},
    }
    // 最贵
    most := books[0]
    for _, b := range books {
        if b.Price > most.Price {
            most = b
        }
    }
    // 排序
    sort.Slice(books, func(i, j int) bool {
        return books[i].Price > books[j].Price
    })
    // 输出...
}

收获 :结构体方法、切片排序、sort.Slice


13. 常见坑点总结

  1. map 必须初始化var m map[string]int 是 nil,直接赋值 panic。

  2. 切片 append 的返回值要接收s = append(s, 1)

  3. for range 的迭代变量是副本:修改值不影响原切片,需用索引。

  4. defer 参数在声明时求值,而非调用时。

  5. 指针不能运算


14. 后续学习方向

  • 并发:goroutine、channel、select

  • 接口 interface

  • 包管理 go mod

  • 标准库:net/http、json、io

  • 错误处理最佳实践


15. 结语

一天的时间,我把 Go 的基础语法和几个典型练习过了一遍。Go 的语法非常简洁,没有繁杂的继承和泛型(泛型已支持,但入门先不深究),代码可读性高,编译速度快。

如果你也在学习 Go,希望这篇博客可以作为一个索引,帮你快速回顾核心知识点。代码示例都是可以独立运行的,建议亲手敲一遍,理解会更深刻。

所有练习的完整代码已整理好,欢迎留言讨论。 学完基础,我们就可以开始写简单的 Web 服务器或并发爬虫啦!

相关推荐
nan madol2 小时前
openEuler部署 Kubernetes v1.35.5 集群
云原生·容器·kubernetes
木雷坞2 小时前
K8s containerd 镜像源配置:用 1ms-helper 处理 ImagePullBackOff
云原生·容器·kubernetes
XMYX-04 小时前
33 - Go 文本模板 template:从入门到原理深挖
golang·正则表达式
米高梅狮子4 小时前
03.OpenStack使用
linux·前端·云原生·容器·架构·kubernetes·openstack
STDD5 小时前
KEDA:Kubernetes 事件驱动自动扩缩容
云原生·容器·kubernetes
weixin_408318045 小时前
企业级直播平台技术选型与成本分析:三种方案架构对比
微服务·云原生·架构
珂玥c5 小时前
k8s集群高可用的碎碎念
云原生·容器·kubernetes
小夏子_riotous6 小时前
Kubernetes学习路径——7. Pod控制器详解
docker·云原生·容器·kubernetes·云计算·paas·kubelet
知彼解己7 小时前
从后端角度理解 AI Agent:理论 + Go 实战(附 MCP 服务器实现)
java·golang·ai编程