从零开始学 Go:协程并发与 Web 开发初探

从零开始学 Go:协程并发与 Web 开发初探

前言

最近开始系统学习 Go 语言,被它简洁的语法和强大的并发模型所吸引。本文是我学习过程中的一些笔记和代码整理,从最基础的语法到协程并发,再到用 Gin 搭建 Web 服务,希望能帮助同样在入门 Go 的同学快速上手。文章会由浅入深,配合可运行的代码示例,让你边看边练。

一、初识 Go:Hello World 与基础语法

1.1 第一个 Go 程序

Go 程序的入口是 main 包下的 main 函数,使用 fmt.Println 输出内容。

go 复制代码
package main

import "fmt"

func main() {
    fmt.Println("hello world")
}

运行方式:

bash 复制代码
go run main.go

1.2 变量声明

Go 是强类型语言,声明变量有两种常用方式:

go 复制代码
// 显式声明类型
var name string = "你好"

// 短变量声明,类型自动推断(只能在函数内使用)
age := 18

注意:age := 18 推断为 int 类型,之后不能再赋值为字符串 age = "22",编译器会报错。

1.3 条件与循环

Go 的 if 语句不需要括号包裹条件,循环只有 for 一种关键字,但可以实现传统 while 的效果。

go 复制代码
if age >= 18 {
    fmt.Println("成年人")
}

// 经典 for 循环
for i := 0; i < 10; i++ {
    fmt.Println(i)
}

1.4 数组、切片与映射

  • 数组 :长度固定,如 [3]int{1,2,3}
  • 切片 :动态数组,使用更灵活,支持 append 追加元素
  • 映射:键值对集合
go 复制代码
// 切片
slice := []int{1, 2, 3}
slice = append(slice, 4) // [1 2 3 4]

// map
m := map[string]int{"a": 1, "b": 2}
fmt.Println(m["a"]) // 输出: 1

1.5 函数与结构体

Go 没有类的概念,但可以通过结构体和方法实现面向对象风格。

go 复制代码
// 普通函数
func add(a int, b int) int {
    return a + b
}

// 结构体定义
type User struct {
    Name string
    Age  int
}

// 创建实例
u := User{Name: "张三", Age: 18}

1.6 指针

Go 支持指针,常用于函数中修改外部变量。

go 复制代码
func updateAge(age *int) {
    *age = 20
}

x := 18
updateAge(&x)
fmt.Println(x) // 20

二、并发编程:goroutine 与 channel

2.1 什么是 goroutine?

Go 语言并发模型的核心是 goroutine,它是由 Go 运行时管理的轻量级线程。你可以把它理解为"协程",但比传统线程更轻量、开销更小,可以轻松创建成千上万个。

用一个厨房比喻来理解:

厨师一次只做一道菜,如果肉菜需要炖 20 分钟,他不用干等,而是利用这段时间去切土豆、准备其他食材------这就相当于 并发,多个任务交替推进,看起来像同时进行。

2.2 开启一个 goroutine

使用 go 关键字即可在后台启动一个新的 goroutine。

go 复制代码
package main

import (
    "fmt"
    "time"
)

func sayHello() {
    fmt.Println("hello world")
}

func main() {
    go sayHello()           // 新开协程执行
    fmt.Println("main")
    time.Sleep(time.Second) // 阻塞主线程,等待协程完成
}

注意 :如果主函数退出,所有 goroutine 都会被强制结束,所以这里用 time.Sleep 简单等待(实际开发中应使用同步机制)。

2.3 通道 channel:协程间通信

goroutine 之间可以通过 channel 安全地传递数据。channel 是类型相关的管道,你可以向它发送数据,也可以从它接收数据。

go 复制代码
package main

import "fmt"

func main() {
    ch := make(chan int) // 创建传递 int 的通道

    go func() {
        ch <- 100 // 发送数据到通道
    }()

    num := <-ch // 从通道接收数据,此处会阻塞等待
    fmt.Println(num) // 100
}

发送和接收操作默认是阻塞的,这天然实现了 goroutine 之间的同步。

三、Web 开发:从 net/http 到 Gin 框架

3.1 标准库搭建 Web 服务器

Go 标准库 net/http 已经提供了基本的 HTTP 服务能力,无需第三方框架即可启动 Web 服务。

go 复制代码
package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "hello world")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

访问 http://localhost:8080 即可看到响应。

3.2 使用 Gin 框架

Gin 是 Go 生态中最流行的 Web 框架之一,类似于 Node.js 中的 Express,它以高性能和简洁的 API 著称,非常适合构建 RESTful 服务。

首先安装 Gin:

bash 复制代码
go get -u github.com/gin-gonic/gin

然后编写一个简单的 JSON 接口:

go 复制代码
package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()

    r.GET("/hello", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "hello world",
        })
    })

    r.Run(":8080")
}
  • gin.Default() 创建默认路由器(自带 Logger 和 Recovery 中间件)
  • r.GET 注册路由和处理函数
  • c.JSON 返回 JSON 格式响应
  • gin.Hmap[string]interface{} 的快捷写法

运行后访问 http://localhost:8080/hello,即可获得 JSON 数据。

3.3 项目依赖管理

你看到的 go.mod 文件是 Go Modules 的配置文件,记录了项目的模块名和依赖版本。当你在项目中导入 Gin 等第三方包时,go.mod 会自动更新依赖树,保证构建的可重现性。

go 复制代码
module gin-demo

go 1.26.2

require (
    github.com/gin-gonic/gin v1.12.0
    // ... 其他间接依赖
)

四、总结与展望

通过以上内容,我们从零开始掌握了 Go 语言的:

  • 基础语法:变量、循环、切片、结构体、指针
  • 并发模型:goroutine 与 channel 的基本使用
  • Web 开发:用标准库和 Gin 框架搭建 HTTP 服务

Go 语言的设计哲学是"少即是多",语法简单但功能强大,尤其在并发和网络编程领域表现突出。后续可以进一步学习:

  • 错误处理与 defer
  • 接口 interface 的妙用
  • 更复杂的并发模式(select、sync 包)
  • 数据库集成(如 MongoDB 驱动)
  • 项目结构设计

如果你也对 Go 感兴趣,不妨跟着这些示例敲一遍代码,你会发现 Go 的简洁与高效确实让人着迷。


相关推荐
运维开发笔记4 小时前
5.2 Go 数组进阶学习笔记(多维、排序、搜索)
go
newerp11 小时前
Redis 操作与缓存策略
后端·程序员·go
newerp12 小时前
GORM ORM 基础
后端·程序员·go
newerp12 小时前
CRUD 操作与预处理语句
后端·程序员·go
程序员爱钓鱼15 小时前
Go 编程实战:闭包 Closure——函数如何记住外部变量
后端·google·go
橘bird1 天前
Go 语言学习教程 万字精讲(新手完整版)
go
用户330144867631 天前
08. mcentral:中心缓存的 span 管理
go
用户330144867631 天前
07. mcache.refill:缓存补充与 span 归还
go
程序员爱钓鱼2 天前
Go 编程实战:匿名函数 Anonymous Function——没有名字的函数与灵活回调
后端·面试·go
用户330144867633 天前
03. Size Class 分级机制
go