Go 语言详细教程

目录

  1. Go 语言简介
  2. 环境搭建
  3. 基础语法
  4. 数据类型
  5. 控制结构
  6. 函数
  7. 数组与切片
  8. Map
  9. 结构体
  10. 接口
  11. 并发编程
  12. 错误处理
  13. 文件操作
  14. 网络编程
  15. 标准库介绍
  16. 实战项目

Go 语言简介

Go(又称 Golang)是 Google 开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。

主要特点:

  • 简洁快速的编译
  • 内置并发支持
  • 垃圾回收
  • 强类型系统
  • 丰富的标准库
  • 跨平台支持

环境搭建

安装 Go

  1. 下载地址:https://golang.org/dl/
  2. 选择适合你操作系统的版本下载并安装
  3. 验证安装: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/O
  • os: 操作系统功能
  • io: 基本I/O接口
  • bufio: 缓冲I/O
  • net/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")
}

进阶学习

  1. Go Modules: 现代Go项目的依赖管理
  2. 性能优化: pprof工具使用
  3. 测试: 单元测试、基准测试和示例测试
  4. 反射: reflect包的使用
  5. CGO: 与C语言的交互
  6. 插件系统: 动态加载代码
  7. Web框架: Gin, Echo等
  8. ORM: GORM等数据库工具

学习资源

希望这个详细的Go语言教程能帮助你快速掌握Go编程!









results matching ""

    No results matching ""