前言 Go(又称 Golang)是由 Google 开发的静态强类型、编译型语言。它语法简洁、并发能力强、编译速度快,广泛应用于后端服务、云原生、微服务、CLI 工具 等领域。知名的 Docker、Kubernetes、Prometheus 都是用 Go 编写的。
本文将从零开始,带你掌握 Go 语言的核心基础。
为什么选择 Go?
优势
说明
🚀 编译快
大型项目几秒内编译完成
🔒 类型安全
静态类型,编译期发现错误
🧵 原生并发
goroutine + channel,简洁高效的并发模型
📦 依赖简单
代码格式化、测试、依赖管理都内置于工具链
🪶 部署简单
编译成单个二进制文件,无需运行时环境
一、环境搭建 1.1 安装 Go 从 go.dev/dl 下载对应系统的安装包,或使用包管理器安装。
Linux(apt):
1 sudo apt install golang-go
macOS(Homebrew):
1.2 验证安装
1.3 配置环境(可选) Go 使用 GOPATH 和 GOMODULE 管理代码。现代 Go 通常使用模块模式:
1 2 go env GOPATH go env GOROOT
二、第一个 Go 程序 1 2 3 4 5 6 7 8 package mainimport "fmt" func main () { fmt.Println("Hello, 七月小站!" ) }
运行 1 2 3 4 5 6 7 go run main.go go build main.go ./main
程序结构解读:
代码
含义
package main
声明包名,可执行程序必须是 main 包
import "fmt"
导入格式化输出包
func main()
程序入口函数
三、变量与常量 3.1 变量声明 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package mainimport "fmt" func main () { var name string = "July" var age int = 25 var city = "深圳" var score = 99.5 language := "Go" count := 10 var ( host string = "localhost" port int = 8080 debug bool = false ) a, b, c := 1 , 2 , 3 fmt.Println(name, age, city, score, language, count) fmt.Println(host, port, debug, a, b, c) }
3.2 常量 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const PI = 3.14159 const ( StatusOK = 200 StatusError = 500 ) const ( Monday = iota Tuesday Wednesday Thursday Friday Saturday Sunday )
四、基本数据类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 var isActive bool = true var i8 int8 = 127 var u8 uint8 = 255 var i16 int16 = 32767 var i32 int32 = 2147483647 var i64 int64 = 9223372036854775807 var i int = 100 var u uint = 200 var f32 float32 = 3.14 var f64 float64 = 3.141592653589793 var s1 string = "Hello" s2 := "七月小站" var b byte = 'A' var r rune = '中'
字符串常用操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import ( "fmt" "strings" ) func main () { s := "Hello, Go!" fmt.Println(len (s)) fmt.Println(strings.Contains(s, "Go" )) fmt.Println(strings.HasPrefix(s, "He" )) fmt.Println(strings.ToUpper(s)) fmt.Println(strings.Split(s, "," )) fmt.Println(strings.ReplaceAll(s, "Go" , "世界" )) fmt.Println(strings.TrimSpace(" hi " )) }
类型转换 Go 不支持隐式类型转换 ,必须显式转换:
1 2 3 4 5 6 7 8 9 10 var i int = 42 var f float64 = float64 (i) var u uint = uint (f) import "strconv" s := strconv.Itoa(42 ) n, _ := strconv.Atoi("42" ) f := strconv.FormatFloat(3.14 , 'f' , 2 , 64 )
五、复合数据类型 5.1 数组(固定长度) 1 2 3 4 5 6 7 8 9 10 11 var arr1 [5 ]int arr2 := [3 ]string {"Go" , "Python" , "Java" } arr3 := [...]int {1 , 2 , 3 , 4 , 5 } fmt.Println(arr2[0 ]) fmt.Println(len (arr3)) for i, v := range arr2 { fmt.Printf("索引: %d, 值: %s\n" , i, v) }
5.2 切片(动态数组,最常用)⭐ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 s1 := []int {1 , 2 , 3 , 4 , 5 } s2 := make ([]int , 3 , 5 ) var s3 []int arr := [5 ]int {1 , 2 , 3 , 4 , 5 } s4 := arr[1 :4 ] s5 := arr[:3 ] s6 := arr[2 :] s1 = append (s1, 6 , 7 , 8 ) s1 = append (s1, s2...) dst := make ([]int , len (s1)) copy (dst, s1)s1 = append (s1[:2 ], s1[3 :]...) fmt.Println(len (s1), cap (s1))
💡 切片 vs 数组 :数组长度固定,切片长度可变。Go 中绝大多数场景用切片。
5.3 Map(字典/映射) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 m1 := map [string ]int { "Go" : 100 , "Python" : 200 , } m2 := make (map [string ]string ) m2["name" ] = "July" m2["blog" ] = "blog.iot2045.cn" delete (m1, "Python" ) value, ok := m2["name" ] fmt.Println(value, ok) for k, v := range m2 { fmt.Printf("key: %s, value: %s\n" , k, v) } if _, ok := m2["email" ]; !ok { fmt.Println("email 不存在" ) }
六、流程控制 6.1 if / else 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 score := 85 if score >= 90 { fmt.Println("优秀" ) } else if score >= 80 { fmt.Println("良好" ) } else if score >= 60 { fmt.Println("及格" ) } else { fmt.Println("不及格" ) } if err := doSomething(); err != nil { fmt.Println("出错了:" , err) }
6.2 switch Go 的 switch 不需要 break,默认只执行匹配的分支:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 day := 3 switch day {case 1 : fmt.Println("星期一" ) case 2 : fmt.Println("星期二" ) case 3 : fmt.Println("星期三" ) default : fmt.Println("其他" ) } switch {case score >= 90 : fmt.Println("A" ) case score >= 80 : fmt.Println("B" ) case score >= 60 : fmt.Println("C" ) default : fmt.Println("D" ) } switch num := 1 ; num {case 1 : fmt.Println("一" ) fallthrough case 2 : fmt.Println("二" ) }
6.3 for 循环 Go 只有 for 一种循环,但可以模拟各种形式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 for i := 0 ; i < 5 ; i++ { fmt.Println(i) } count := 0 for count < 5 { fmt.Println(count) count++ } for { break } nums := []int {10 , 20 , 30 } for index, value := range nums { fmt.Printf("索引: %d, 值: %d\n" , index, value) } for i := range nums { fmt.Println(i) } for _, v := range nums { fmt.Println(v) }
6.4 break / continue 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 for i := 0 ; i < 10 ; i++ { if i == 5 { break } fmt.Println(i) } for i := 0 ; i < 5 ; i++ { if i == 2 { continue } fmt.Println(i) } outer: for i := 0 ; i < 3 ; i++ { for j := 0 ; j < 3 ; j++ { if i == 1 && j == 1 { break outer } fmt.Printf("(%d, %d) " , i, j) } }
七、函数 7.1 基本函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 func sayHello (name string ) { fmt.Printf("Hello, %s!\n" , name) } func add (a, b int ) int { return a + b } func divide (a, b float64 ) (float64 , error ) { if b == 0 { return 0 , fmt.Errorf("除数不能为零" ) } return a / b, nil } func split (sum int ) (x, y int ) { x = sum * 4 / 9 y = sum - x return } func sum (nums ...int ) int { total := 0 for _, n := range nums { total += n } return total } func main () { sayHello("July" ) fmt.Println(add(3 , 5 )) result, err := divide(10 , 3 ) if err != nil { fmt.Println("错误:" , err) } else { fmt.Println("结果:" , result) } fmt.Println(sum(1 , 2 , 3 , 4 , 5 )) }
7.2 函数作为值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 add := func (a, b int ) int { return a + b } func apply (nums []int , fn func (int ) int ) []int { result := make ([]int , len (nums)) for i, v := range nums { result[i] = fn(v) } return result } func main () { double := func (x int ) int { return x * 2 } nums := []int {1 , 2 , 3 } fmt.Println(apply(nums, double)) }
7.3 defer — 延迟执行 defer 在函数返回前执行,常用于资源清理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func readFile (path string ) error { file, err := os.Open(path) if err != nil { return err } defer file.Close() return nil } func demo () { defer fmt.Println("1" ) defer fmt.Println("2" ) defer fmt.Println("3" ) fmt.Println("hello" ) }
八、结构体与自定义类型 8.1 结构体定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 type User struct { ID int Username string Email string Age int IsActive bool } func main () { u1 := User{ ID: 1 , Username: "july" , Email: "july@example.com" , Age: 25 , } u2 := User{2 , "zhangsan" , "zhangsan@example.com" , 30 , true } var u3 User u3.Username = "lisi" point := struct { X, Y int }{10 , 20 } fmt.Println(u1, u2, u3, point) }
8.2 方法(给类型绑定函数) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 func (u User) DisplayName() string { return fmt.Sprintf("%s (%s)" , u.Username, u.Email) } func (u *User) SetEmail(email string ) { u.Email = email } func NewUser (username, email string ) *User { return &User{ Username: username, Email: email, IsActive: true , } } func main () { user := NewUser("july" , "july@example.com" ) fmt.Println(user.DisplayName()) user.SetEmail("new@example.com" ) fmt.Println(user.Email) }
九、接口(Interface) Go 的接口是隐式实现 的——不需要显式声明 implements,只要实现了接口的所有方法就算实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 type Animal interface { Speak() string Move() string } type Cat struct { Name string } func (c Cat) Speak() string { return "喵喵喵" } func (c Cat) Move() string { return "悄悄地走" } type Dog struct { Name string } func (d Dog) Speak() string { return "汪汪汪" } func (d Dog) Move() string { return "跑着走" } func MakeAnimalAct (a Animal) { fmt.Printf("%T 说: %s, 移动: %s\n" , a, a.Speak(), a.Move()) } func main () { cat := Cat{Name: "小花" } dog := Dog{Name: "旺财" } MakeAnimalAct(cat) MakeAnimalAct(dog) var anything any anything = "hello" anything = 42 anything = []int {1 , 2 , 3 } fmt.Println(anything) var a Animal = cat c, ok := a.(Cat) if ok { fmt.Println("这是一只猫:" , c.Name) } }
十、错误处理 Go 不使用 try-catch,而是通过多返回值显式处理错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import ( "errors" "fmt" "os" ) func validateAge (age int ) error { if age < 0 { return errors.New("年龄不能为负数" ) } if age > 150 { return fmt.Errorf("年龄 %d 超出合理范围" , age) } return nil } func readConfig (path string ) (string , error ) { data, err := os.ReadFile(path) if err != nil { return "" , fmt.Errorf("读取配置失败: %w" , err) } return string (data), nil } func main () { if err := validateAge(-5 ); err != nil { fmt.Println("验证失败:" , err) } config, err := readConfig("/etc/app.conf" ) if err != nil { fmt.Println("错误:" , err) return } fmt.Println(config) }
十一、并发编程(goroutine)⭐ 并发是 Go 最大的亮点。
11.1 goroutine — 轻量级线程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import ( "fmt" "time" ) func printNumbers () { for i := 1 ; i <= 5 ; i++ { fmt.Printf("%d " , i) time.Sleep(100 * time.Millisecond) } } func main () { go printNumbers() fmt.Println("主程序继续..." ) time.Sleep(600 * time.Millisecond) fmt.Println("\n主程序结束" ) }
11.2 channel — goroutine 间通信 Go 的核心哲学:不要通过共享内存来通信,而要通过通信来共享内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 func demo1 () { ch := make (chan string ) go func () { ch <- "你好,来自 goroutine" }() msg := <-ch fmt.Println(msg) } func demo2 () { ch := make (chan int , 3 ) ch <- 1 ch <- 2 ch <- 3 fmt.Println(<-ch) fmt.Println(<-ch) fmt.Println(<-ch) } func producer (ch chan <- int ) { for i := 1 ; i <= 5 ; i++ { ch <- i fmt.Printf("生产: %d\n" , i) } close (ch) } func consumer (ch <-chan int ) { for num := range ch { fmt.Printf("消费: %d\n" , num) } } func main () { ch := make (chan int , 2 ) go producer(ch) consumer(ch) }
11.3 select — 多路复用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 func main () { ch1 := make (chan string ) ch2 := make (chan string ) go func () { time.Sleep(1 * time.Second) ch1 <- "来自 ch1" }() go func () { time.Sleep(2 * time.Second) ch2 <- "来自 ch2" }() for i := 0 ; i < 2 ; i++ { select { case msg1 := <-ch1: fmt.Println("收到:" , msg1) case msg2 := <-ch2: fmt.Println("收到:" , msg2) case <-time.After(3 * time.Second): fmt.Println("超时!" ) } } }
11.4 sync.WaitGroup — 等待 goroutine 完成 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import ( "fmt" "sync" ) func worker (id int , wg *sync.WaitGroup) { defer wg.Done() fmt.Printf("Worker %d 开始\n" , id) fmt.Printf("Worker %d 完成\n" , id) } func main () { var wg sync.WaitGroup for i := 1 ; i <= 5 ; i++ { wg.Add(1 ) go worker(i, &wg) } wg.Wait() fmt.Println("所有 worker 完成" ) }
十二、包管理(Go Modules) 12.1 初始化模块 1 go mod init github.com/yourname/myproject
生成 go.mod 文件:
1 2 3 module github.com/yourname/myproject go 1.22
12.2 安装依赖 1 2 go get github.com/gin-gonic/gin go mod tidy
12.3 自定义包 项目结构:
1 2 3 4 5 myproject/ ├── go.mod ├── main.go └── utils/ └── math.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package utilsfunc Add (a, b int ) int { return a + b } var Version = "1.0.0" func internalHelper () string { return "内部函数" }
1 2 3 4 5 6 7 8 9 10 11 12 package mainimport ( "fmt" "github.com/yourname/myproject/utils" ) func main () { fmt.Println(utils.Add(1 , 2 )) fmt.Println(utils.Version) }
十三、实战:构建一个 HTTP 服务器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 package mainimport ( "encoding/json" "net/http" "strconv" "sync" ) type Article struct { ID int `json:"id"` Title string `json:"title"` Content string `json:"content"` } var ( articles = make (map [int ]Article) mu sync.RWMutex nextID = 1 ) func listArticles (w http.ResponseWriter, r *http.Request) { mu.RLock() defer mu.RUnlock() var result []Article for _, a := range articles { result = append (result, a) } w.Header().Set("Content-Type" , "application/json" ) json.NewEncoder(w).Encode(result) } func createArticle (w http.ResponseWriter, r *http.Request) { var article Article json.NewDecoder(r.Body).Decode(&article) mu.Lock() article.ID = nextID nextID++ articles[article.ID] = article mu.Unlock() w.Header().Set("Content-Type" , "application/json" ) w.WriteHeader(http.StatusCreated) json.NewEncoder(w).Encode(article) } func getArticle (w http.ResponseWriter, r *http.Request) { idStr := r.PathValue("id" ) id, _ := strconv.Atoi(idStr) mu.RLock() article, ok := articles[id] mu.RUnlock() if !ok { http.NotFound(w, r) return } w.Header().Set("Content-Type" , "application/json" ) json.NewEncoder(w).Encode(article) } func deleteArticle (w http.ResponseWriter, r *http.Request) { idStr := r.PathValue("id" ) id, _ := strconv.Atoi(idStr) mu.Lock() delete (articles, id) mu.Unlock() w.WriteHeader(http.StatusNoContent) } func main () { mux := http.NewServeMux() mux.HandleFunc("GET /api/articles" , listArticles) mux.HandleFunc("POST /api/articles" , createArticle) mux.HandleFunc("GET /api/articles/{id}" , getArticle) mux.HandleFunc("DELETE /api/articles/{id}" , deleteArticle) fmt.Println("服务器启动于 http://localhost:8080" ) http.ListenAndServe(":8080" , mux) }
启动并测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 go run main.go curl -X POST http://localhost:8080/api/articles \ -H "Content-Type: application/json" \ -d '{"title":"Go入门","content":"Go语言真好学"}' curl http://localhost:8080/api/articles curl http://localhost:8080/api/articles/1 curl -X DELETE http://localhost:8080/api/articles/1
常用 Go 命令速查
命令
说明
go run main.go
运行程序
go build
编译为二进制
go build -o app
指定输出文件名
go fmt ./...
格式化代码
go vet ./...
静态检查
go test ./...
运行测试
go mod init name
初始化模块
go mod tidy
整理依赖
go get pkg
安装依赖
go doc fmt.Println
查看文档
go env
查看环境变量
CGO_ENABLED=0 go build
静态编译(容器部署用)
进一步学习
标准库 :net/http、encoding/json、database/sql、context、testing
Web 框架 :Gin、Echo、Fiber
ORM :GORM
项目实战 :写一个 CLI 工具(使用 cobra 库),或一个 RESTful API
Go 箴言 :理解 Go 的设计哲学——简洁、组合优于继承、显式错误处理
结语 Go 语言的核心理念是简洁即力量 。它没有花哨的语法糖,没有继承和泛型(1.18 开始有有限的泛型),但正是这份克制让它成为构建可靠、高效系统的最佳选择之一。
本文覆盖了 Go 语言 80% 的常用知识点。建议从写一个小项目开始实践——比如一个简单的 Todo API 或文件处理工具,在实践中巩固所学。
写 Go 的第一天可能不习惯,一周后你会爱上它的简洁。 💙