Go 语言详细教程
目录
- Go 语言简介
- 环境搭建
- 基础语法
- 数据类型
- 控制结构
- 函数
- 数组与切片
- Map
- 结构体
- 接口
- 并发编程
- 错误处理
- 文件操作
- 网络编程
- 标准库介绍
- 实战项目
Go 语言简介
Go(又称 Golang)是 Google 开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。
主要特点:
- 简洁快速的编译
- 内置并发支持
- 垃圾回收
- 强类型系统
- 丰富的标准库
- 跨平台支持
环境搭建
安装 Go
- 下载地址:https://golang.org/dl/
- 选择适合你操作系统的版本下载并安装
- 验证安装:
go version
配置环境变量
GOROOT
: Go 安装目录GOPATH
: 工作目录(包含 src, bin, pkg)PATH
: 添加$GOROOT/bin
和$GOPATH/bin
开发工具推荐
- Visual Studio Code + Go 插件
- Goland
- LiteIDE
基础语法
Hello World 程序
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
包管理
- 每个 Go 文件都属于一个包
main
包是程序入口- 导入包使用
import
关键字
变量声明
// 单变量声明
var name string = "Go"
// 类型推断
var age = 10
// 短变量声明(函数内)
score := 100
// 多变量声明
var x, y int = 1, 2
常量
const Pi = 3.14
const (
StatusOK = 200
StatusNotFound = 404
)
数据类型
基本类型
- 布尔:
bool
数字:
- 整数:
int
,int8
,int16
,int32
,int64
,uint
,uint8
,uint16
,uint32
,uint64
,uintptr
- 浮点:
float32
,float64
- 复数:
complex64
,complex128
- 整数:
- 字符串:
string
- 字节:
byte
(uint8 别名) - 符文:
rune
(int32 别名)
类型转换
Go 要求显式类型转换:
var i int = 42
var f float64 = float64(i)
var u uint = uint(f)
控制结构
条件语句
if x > 10 {
fmt.Println("x is greater than 10")
} else if x == 10 {
fmt.Println("x is equal to 10")
} else {
fmt.Println("x is less than 10")
}
循环
Go 只有 for
循环:
// 传统for循环
for i := 0; i < 10; i++ {
fmt.Println(i)
}
// while循环的替代
sum := 1
for sum < 1000 {
sum += sum
}
// 无限循环
for {
// ...
}
Switch
switch os := runtime.GOOS; os {
case "darwin":
fmt.Println("OS X")
case "linux":
fmt.Println("Linux")
default:
fmt.Printf("%s\n", os)
}
函数
基本函数
func add(x int, y int) int {
return x + y
}
// 参数类型简写
func add(x, y int) int {
return x + y
}
多返回值
func swap(x, y string) (string, string) {
return y, x
}
a, b := swap("hello", "world")
命名返回值
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
可变参数
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
fmt.Println(sum(1, 2, 3))
数组与切片
数组
// 声明数组
var a [5]int
// 初始化数组
b := [5]int{1, 2, 3, 4, 5}
// 二维数组
var twoD [2][3]int
切片
切片是数组的抽象,更灵活:
// 创建切片
s := make([]string, 3)
// 从数组创建
arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:4] // [2, 3, 4]
// 切片操作
s = append(s, "d")
copy(s2, s1) // 复制切片
Map
// 创建map
m := make(map[string]int)
// 初始化map
m := map[string]int{
"one": 1,
"two": 2,
}
// 操作map
m["key"] = 42
delete(m, "key")
elem, ok := m["key"] // 检查key是否存在
结构体
// 定义结构体
type Person struct {
name string
age int
}
// 创建结构体实例
p := Person{"Alice", 20}
// 访问字段
fmt.Println(p.name)
// 结构体指针
pp := &p
fmt.Println(pp.age) // 自动解引用
方法
// 为结构体定义方法
func (p Person) sayHello() {
fmt.Printf("Hello, my name is %s\n", p.name)
}
// 指针接收者方法
func (p *Person) birthday() {
p.age++
}
接口
// 定义接口
type Speaker interface {
Speak() string
}
// 实现接口
type Dog struct{}
func (d Dog) Speak() string {
return "Woof!"
}
// 使用接口
var s Speaker = Dog{}
fmt.Println(s.Speak())
并发编程
Goroutine
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
go say("world") // 启动goroutine
say("hello")
Channel
// 创建channel
ch := make(chan int)
// 发送和接收
go func() {
ch <- 42
}()
value := <-ch
// 带缓冲的channel
ch := make(chan int, 2)
ch <- 1
ch <- 2
// 关闭channel
close(ch)
// range遍历channel
for i := range ch {
fmt.Println(i)
}
Select
select {
case msg1 := <-ch1:
fmt.Println("received", msg1)
case msg2 := <-ch2:
fmt.Println("received", msg2)
case ch3 <- 3:
fmt.Println("sent 3")
default:
fmt.Println("no communication")
}
错误处理
Go 使用返回值而不是异常来处理错误:
func divide(a, b float64) (float64, error) {
if b == 0.0 {
return 0.0, fmt.Errorf("cannot divide by zero")
}
return a / b, nil
}
result, err := divide(10, 0)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(result)
文件操作
读取文件
data, err := ioutil.ReadFile("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
写入文件
content := []byte("Hello, Go!")
err := ioutil.WriteFile("test.txt", content, 0644)
if err != nil {
log.Fatal(err)
}
逐行读取
file, err := os.Open("test.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
网络编程
HTTP 服务器
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
HTTP 客户端
resp, err := http.Get("http://example.com/")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
标准库介绍
Go 拥有丰富的标准库,常用包包括:
fmt
: 格式化I/Oos
: 操作系统功能io
: 基本I/O接口bufio
: 缓冲I/Onet/http
: HTTP客户端和服务器encoding/json
: JSON编解码sync
: 并发同步原语time
: 时间处理strings
: 字符串操作strconv
: 字符串转换
实战项目
1. 简单的Web服务
package main
import (
"encoding/json"
"net/http"
)
type Message struct {
Text string `json:"text"`
}
func main() {
http.HandleFunc("/api/message", func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
message := Message{Text: "Hello from Go!"}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(message)
})
http.ListenAndServe(":8080", nil)
}
2. 并发文件处理
package main
import (
"fmt"
"io/ioutil"
"path/filepath"
"sync"
)
func processFile(path string, wg *sync.WaitGroup) {
defer wg.Done()
content, err := ioutil.ReadFile(path)
if err != nil {
fmt.Printf("Error reading %s: %v\n", path, err)
return
}
fmt.Printf("File %s has %d bytes\n", path, len(content))
}
func main() {
files, err := filepath.Glob("*.txt")
if err != nil {
fmt.Println("Error finding files:", err)
return
}
var wg sync.WaitGroup
for _, file := range files {
wg.Add(1)
go processFile(file, &wg)
}
wg.Wait()
fmt.Println("All files processed")
}
进阶学习
- Go Modules: 现代Go项目的依赖管理
- 性能优化: pprof工具使用
- 测试: 单元测试、基准测试和示例测试
- 反射: reflect包的使用
- CGO: 与C语言的交互
- 插件系统: 动态加载代码
- Web框架: Gin, Echo等
- ORM: GORM等数据库工具
学习资源
- 官方文档: https://golang.org/doc/
- 官方教程: https://tour.golang.org
- 标准库文档: https://golang.org/pkg/
- Go by Example: https://gobyexample.com/
- 《Go语言圣经》: https://books.studygolang.com/gopl-zh/
希望这个详细的Go语言教程能帮助你快速掌握Go编程!