Go语言基础入门指南

前言

Go语言(也称为Golang)是Google开发的一种静态强类型、编译型语言。自2009年发布以来,Go凭借其简洁的语法、出色的并发性能和快速的编译速度,在云计算、微服务、区块链等领域得到了广泛应用。

为什么选择Go语言?

1. 语言特性优势

  • 简洁易学:语法简单,关键字仅25个
  • 高性能:编译型语言,接近C语言的执行效率
  • 并发友好:原生支持goroutine和channel
  • 快速编译:编译速度极快,提升开发效率
  • 内存安全:自动垃圾回收,避免内存泄漏

2. 生态系统完善

1
2
3
4
5
# Go的包管理工具
go mod init myproject
go get github.com/gin-gonic/gin
go build
go run main.go

Go语言基础语法

1. 环境搭建

安装Go

1
2
3
4
5
6
7
8
9
10
11
# macOS
brew install go

# Linux
wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz

# 配置环境变量
export PATH=$PATH:/usr/local/go/bin
export GOPATH=$HOME/go
export GOROOT=/usr/local/go

验证安装

1
2
go version
# 输出: go version go1.21.0 darwin/amd64

2. Hello World程序

1
2
3
4
5
6
7
package main

import "fmt"

func main() {
fmt.Println("Hello, World!")
}
1
2
3
4
5
# 运行程序
go run main.go
# 或编译后运行
go build main.go
./main

3. 基本数据类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "fmt"

func main() {
// 基本类型
var name string = "Go语言"
var age int = 15
var isActive bool = true
var score float64 = 98.5

// 短变量声明
language := "Golang"
year := 2009

// 常量
const PI = 3.14159
const MaxUsers = 1000

fmt.Printf("语言: %s, 年龄: %d岁, 活跃: %t, 评分: %.1f\n",
name, age, isActive, score)
fmt.Printf("别名: %s, 发布年份: %d\n", language, year)
}

4. 数组和切片

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
package main

import "fmt"

func main() {
// 数组
var numbers [5]int = [5]int{1, 2, 3, 4, 5}
languages := [3]string{"Go", "Python", "Java"}

// 切片
slice := []int{10, 20, 30, 40, 50}
slice = append(slice, 60, 70)

// 切片操作
subSlice := slice[1:4] // [20, 30, 40]

fmt.Println("数组:", numbers)
fmt.Println("语言:", languages)
fmt.Println("切片:", slice)
fmt.Println("子切片:", subSlice)

// 遍历
for i, v := range slice {
fmt.Printf("索引: %d, 值: %d\n", i, v)
}
}

5. 映射(Map)

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
package main

import "fmt"

func main() {
// 创建map
userAges := make(map[string]int)
userAges["Alice"] = 25
userAges["Bob"] = 30
userAges["Charlie"] = 35

// 字面量创建
scores := map[string]int{
"数学": 95,
"英语": 88,
"物理": 92,
}

// 访问和检查
age, exists := userAges["Alice"]
if exists {
fmt.Printf("Alice的年龄: %d\n", age)
}

// 遍历
for subject, score := range scores {
fmt.Printf("%s: %d分\n", subject, score)
}

// 删除
delete(userAges, "Bob")
fmt.Println("删除Bob后:", userAges)
}

函数和方法

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
48
package main

import "fmt"

// 基本函数
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 calculate(a, b int) (sum, product int) {
sum = a + b
product = a * b
return // 自动返回命名的返回值
}

// 可变参数
func sum(numbers ...int) int {
total := 0
for _, num := range numbers {
total += num
}
return total
}

func main() {
fmt.Println("加法:", add(3, 5))

result, err := divide(10, 3)
if err != nil {
fmt.Println("错误:", err)
} else {
fmt.Printf("除法结果: %.2f\n", result)
}

s, p := calculate(4, 6)
fmt.Printf("和: %d, 积: %d\n", s, p)

fmt.Println("求和:", sum(1, 2, 3, 4, 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
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main

import "fmt"

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

// 方法
func (p Person) Introduce() string {
return fmt.Sprintf("我是%s,今年%d岁,来自%s", p.Name, p.Age, p.City)
}

// 指针接收者方法
func (p *Person) HaveBirthday() {
p.Age++
}

// 构造函数
func NewPerson(name, city string, age int) *Person {
return &Person{
Name: name,
Age: age,
City: city,
}
}

func main() {
// 创建结构体实例
person1 := Person{
Name: "张三",
Age: 25,
City: "北京",
}

person2 := NewPerson("李四", "上海", 30)

fmt.Println(person1.Introduce())
fmt.Println(person2.Introduce())

// 调用指针方法
person1.HaveBirthday()
fmt.Printf("%s现在%d岁了\n", person1.Name, person1.Age)
}

接口和多态

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
48
49
50
51
52
53
54
55
56
57
package main

import "fmt"

// 定义接口
type Shape interface {
Area() float64
Perimeter() float64
}

// 实现接口的结构体
type Rectangle struct {
Width, Height float64
}

func (r Rectangle) Area() float64 {
return r.Width * r.Height
}

func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}

type Circle struct {
Radius float64
}

func (c Circle) Area() float64 {
return 3.14159 * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
return 2 * 3.14159 * c.Radius
}

// 使用接口
func PrintShapeInfo(s Shape) {
fmt.Printf("面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
rect := Rectangle{Width: 5, Height: 3}
circle := Circle{Radius: 4}

fmt.Println("矩形信息:")
PrintShapeInfo(rect)

fmt.Println("圆形信息:")
PrintShapeInfo(circle)

// 接口切片
shapes := []Shape{rect, circle}
for i, shape := range shapes {
fmt.Printf("形状%d: ", i+1)
PrintShapeInfo(shape)
}
}

并发编程

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
package main

import (
"fmt"
"time"
)

func sayHello(name string) {
for i := 0; i < 3; i++ {
fmt.Printf("Hello, %s! (%d)\n", name, i+1)
time.Sleep(100 * time.Millisecond)
}
}

func main() {
// 启动goroutine
go sayHello("Alice")
go sayHello("Bob")

// 主goroutine等待
time.Sleep(500 * time.Millisecond)
fmt.Println("程序结束")
}

2. Channel通信

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
package main

import (
"fmt"
"time"
)

func producer(ch chan<- int) {
for i := 1; i <= 5; i++ {
fmt.Printf("生产: %d\n", i)
ch <- i
time.Sleep(100 * time.Millisecond)
}
close(ch)
}

func consumer(ch <-chan int) {
for value := range ch {
fmt.Printf("消费: %d\n", value)
time.Sleep(200 * time.Millisecond)
}
}

func main() {
// 创建channel
ch := make(chan int, 2) // 带缓冲的channel

go producer(ch)
go consumer(ch)

time.Sleep(2 * time.Second)
}

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
26
27
28
29
30
31
32
package main

import (
"fmt"
"time"
)

func main() {
ch1 := make(chan string)
ch2 := make(chan string)

go func() {
time.Sleep(100 * time.Millisecond)
ch1 <- "来自channel1的消息"
}()

go func() {
time.Sleep(200 * time.Millisecond)
ch2 <- "来自channel2的消息"
}()

for i := 0; i < 2; i++ {
select {
case msg1 := <-ch1:
fmt.Println("收到:", msg1)
case msg2 := <-ch2:
fmt.Println("收到:", msg2)
case <-time.After(300 * time.Millisecond):
fmt.Println("超时")
}
}
}

错误处理

1. 基本错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package main

import (
"errors"
"fmt"
)

func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("除数不能为零")
}
return a / b, nil
}

func main() {
result, err := divide(10, 0)
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Println("结果:", result)
}

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package main

import "fmt"

type ValidationError struct {
Field string
Message string
}

func (e ValidationError) Error() string {
return fmt.Sprintf("验证错误 - %s: %s", e.Field, e.Message)
}

func validateAge(age int) error {
if age < 0 {
return ValidationError{
Field: "age",
Message: "年龄不能为负数",
}
}
if age > 150 {
return ValidationError{
Field: "age",
Message: "年龄不能超过150岁",
}
}
return nil
}

func main() {
ages := []int{25, -5, 200}

for _, age := range ages {
if err := validateAge(age); err != nil {
fmt.Printf("年龄 %d: %s\n", age, err)
} else {
fmt.Printf("年龄 %d: 有效\n", age)
}
}
}

实战项目:简单Web服务器

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
95
96
97
98
99
100
101
package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
"time"
)

type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
CreateAt time.Time `json:"created_at"`
}

var users []User
var nextID = 1

func main() {
// 初始化数据
users = append(users, User{
ID: nextID,
Name: "张三",
Email: "zhangsan@example.com",
CreateAt: time.Now(),
})
nextID++

// 路由
http.HandleFunc("/users", handleUsers)
http.HandleFunc("/users/", handleUserByID)
http.HandleFunc("/health", handleHealth)

fmt.Println("服务器启动在 :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}

func handleUsers(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case "GET":
getUsersHandler(w, r)
case "POST":
createUserHandler(w, r)
default:
http.Error(w, "方法不允许", http.StatusMethodNotAllowed)
}
}

func getUsersHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}

func createUserHandler(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "无效的JSON", http.StatusBadRequest)
return
}

user.ID = nextID
user.CreateAt = time.Now()
nextID++

users = append(users, user)

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}

func handleUserByID(w http.ResponseWriter, r *http.Request) {
idStr := r.URL.Path[len("/users/"):]
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(w, "无效的用户ID", http.StatusBadRequest)
return
}

for _, user := range users {
if user.ID == id {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(user)
return
}
}

http.Error(w, "用户未找到", http.StatusNotFound)
}

func handleHealth(w http.ResponseWriter, r *http.Request) {
response := map[string]string{
"status": "healthy",
"time": time.Now().Format(time.RFC3339),
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}

学习路径建议

1. 基础阶段(1-2周)

  • ✅ 掌握基本语法和数据类型
  • ✅ 理解函数和方法
  • ✅ 学习结构体和接口

2. 进阶阶段(2-3周)

  • 🔧 深入学习并发编程
  • 🔧 掌握错误处理模式
  • 🔧 学习包管理和模块系统

3. 实战阶段(3-4周)

  • 🚀 构建Web应用
  • 🚀 学习数据库操作
  • 🚀 掌握测试和部署

常用工具和库

1. Web框架

1
2
3
4
5
# Gin - 高性能Web框架
go get github.com/gin-gonic/gin

# Echo - 简洁的Web框架
go get github.com/labstack/echo/v4

2. 数据库

1
2
3
4
5
6
# GORM - ORM库
go get gorm.io/gorm
go get gorm.io/driver/mysql

# Redis客户端
go get github.com/go-redis/redis/v8

3. 工具库

1
2
3
4
5
6
7
8
# UUID生成
go get github.com/google/uuid

# 配置管理
go get github.com/spf13/viper

# 日志库
go get github.com/sirupsen/logrus

总结

Go语言以其简洁的语法、强大的并发能力和优秀的性能,成为现代软件开发的重要选择。通过本指南的学习,你应该能够:

  1. ✅ 掌握Go语言的基本语法和特性
  2. ✅ 理解Go的并发编程模型
  3. ✅ 能够构建简单的Web应用
  4. ✅ 具备继续深入学习的基础

下一步学习建议

  1. 深入并发编程:学习更复杂的并发模式
  2. 微服务开发:使用Go构建微服务架构
  3. 性能优化:学习Go程序的性能调优
  4. 开源贡献:参与Go社区的开源项目

Go语言的学习之路才刚刚开始,持续实践和探索将帮助你成为优秀的Go开发者!


本文涵盖了Go语言的核心概念和实战应用,希望能帮助你快速入门Go语言开发。如有疑问,欢迎交流讨论!