「笔记001」Go语法基础2

2024 年 11 月 21 日 星期四(已编辑)
10
摘要
本文介绍了 Go 语言的一些核心概念和使用注意事项。 1. 结构体与方法:说明了结构体的定义与方法的使用,分为值接收器和指针接收器,强调方法名必须唯一,并注意指针初始化。 2. 字符串与 Range:介绍 Go 语言中的字符串操作和遍历技巧,强调 Unicode 处理和字符串的不可变性。 3. 时间处理:讲解了 Go 中时间获取、格式化和时间差的计算,注意时区处理。 4. JSON 处理:介绍了序列化与反序列化,强调 JSON 字段与结构体字段匹配的重要性。 5. 协程与通道:涵盖 Goroutine 和 Channel 的使用,强调避免协程泄漏和阻塞。 6. 文件与 IO 操作:描述文件的读写操作及缓冲 IO 的使用,注意资源的正确管理。
这篇文章上次修改于 2024 年 11 月 21 日 星期四,可能部分内容已经不适用,如有疑问可询问作者。

阅读此文章之前,你可能需要首先阅读以下的文章才能更好的理解上下文。

「笔记001」Go语法基础2

一、结构体与方法

1. 结构体的基本定义与使用

结构体(struct)是 Go 描述复杂数据的核心工具,用于组织不同类型的字段。

示例代码: ```go type User struct { Name string Age int IsActive bool }

func main() { user := User{Name: "Alice", Age: 25, IsActive: true} fmt.Println(user.Name) // Alice } ```

2. 方法的定义与指针接收器

Go 不直接支持类与继承,但可以为结构体定义方法。方法可分为值接收器和指针接收器:

  • 值接收器:方法作用于结构体的副本,无法修改原结构体内容。
  • 指针接收器:允许修改原结构体内容。
type User struct {
    Name string
    Age  int
}

func (u *User) IncrementAge() {
    u.Age++
}

func main() {
    user := User{Name: "Bob", Age: 30}
    user.IncrementAge()
    fmt.Println(user.Age) // 31
}

知识点讲解:

  • 指针接收器推荐使用场景:结构体较大时,使用指针接收器避免不必要的内存拷贝。
  • 值接收器的适用场景:仅需读取数据且无需修改结构体内容。

注意事项:

  • Go 中的方法不支持重载,同一类型下的方法名必须唯一。
  • 指针接收器需注意初始化问题,避免 nil 指针调用方法。

二、字符串与 Range

1. 字符串操作

Go 提供了强大的 strings 包,用于字符串处理。常用操作包括:

  • 检查子串go fmt.Println(strings.Contains("hello", "ll")) // true
  • 字符串替换go fmt.Println(strings.Replace("hello", "l", "L", -1)) // heLLo
  • 字符串分割go parts := strings.Split("a,b,c", ",") fmt.Println(parts) // [a b c]

2. Range 遍历

range 是 Go 的高级遍历工具,用于字符串、数组、切片、Map 等数据结构。 go for i, c := range "hello" { fmt.Printf("%d: %c\n", i, c) }

知识点讲解:

  • Unicode 字符处理range 会自动处理 Unicode 编码,适合多语言字符串的遍历。
  • 字符串不可变:Go 的字符串是不可变的,每次修改都会生成新的字符串。

注意事项:

  • 对于长字符串的频繁修改,建议使用 strings.Builder 提升性能。
  • 字符串分割时,确保目标字符串符合预期格式,避免索引超出范围。

三、时间处理

Go 的 time 包提供了丰富的时间操作功能,包括获取当前时间、格式化时间和计算时间差。

1. 时间获取与格式化

now := time.Now()
fmt.Println(now.Format("2006-01-02 15:04:05")) // 格式化当前时间

2. 时间差计算

start := time.Now()
// 模拟耗时操作
time.Sleep(2 * time.Second)
elapsed := time.Since(start)
fmt.Println("Elapsed:", elapsed) // Elapsed: 2s

知识点讲解:

  • 时间格式化规则:Go 使用固定的日期 2006-01-02 15:04:05 作为模板。
  • 时间戳与 UTCUnix() 返回秒级时间戳,而 UnixNano() 返回纳秒级时间戳。

注意事项:

  • 时间运算涉及时区时需注意统一时区。
  • 使用 time.Parse 解析字符串时,确保格式与模板一致。

四、JSON 处理

JSON 是现代开发中最常用的数据交换格式,Go 提供了内置的 encoding/json 包处理 JSON 数据。

1. JSON 序列化与反序列化

  • 结构体序列化``go type User struct { Name stringjson:"name"Age intjson:"age"` }

    user := User{Name: "Alice", Age: 25} jsonData, _ := json.Marshal(user) fmt.Println(string(jsonData)) // {"name":"Alice","age":25} ```

  • 结构体反序列化go var decoded User json.Unmarshal([]byte(`{"name":"Alice","age":25}`), &decoded) fmt.Println(decoded.Name) // Alice

知识点讲解:

  • JSON 标签:结构体字段名与 JSON 字段映射通过 json 标签控制,标签区分大小写。
  • 嵌套结构体:嵌套结构体的字段需确保 JSON 标签完整匹配。

注意事项:

  • 字段首字母必须大写以导出为 JSON,否则会被忽略。
  • JSON 字符串中的字段值类型需与结构体字段类型一致。

五、协程与通道

1. 协程(Goroutine)

Go 原生支持轻量级线程,协程的启动使用 go 关键字。 go go func() { fmt.Println("Hello, Goroutine!") }()

2. 通道(Channel)

通道是协程间通信的桥梁,支持无缓冲和缓冲两种模式: go ch := make(chan int) go func() { ch <- 42 }() fmt.Println(<-ch) // 42

3. Select 多路复用

select 监听多个通道操作: go select { case msg := <-ch1: fmt.Println("Received", msg) case msg := <-ch2: fmt.Println("Received", msg) default: fmt.Println("No message received") }

知识点讲解:

  • 无缓冲通道:数据发送和接收必须同时进行。
  • 缓冲通道:允许在通道中存储一定数量的数据,发送方不必立即等待接收方。
  • 协程泄漏:确保协程退出时适当关闭通道,避免资源泄漏。

注意事项:

  • 使用通道时需避免死锁,确保有对应的接收方。
  • selectdefault 分支可避免通道阻塞,但需谨慎使用。

六、文件与 IO 操作

1. 文件读写

Go 的 os 包提供了文件读写的基础操作:

  • 写文件: ```go file, err := os.Create("example.txt") if err != nil { fmt.Println("Error:", err) return } defer file.Close()

    file.WriteString("Hello, Go!") ```

  • 读文件go data, err := os.ReadFile("example.txt") fmt.Println(string(data)) // Hello, Go!

2. 缓冲 IO

bufio 包提供了高效的文件读取方式: ```go file, _ := os.Open("example.txt") defer file.Close()

scanner := bufio.NewScanner(file) for scanner.Scan() { fmt.Println(scanner.Text()) } ```

注意事项:

  • 确保文件操作前后正确关闭文件,避免资源泄漏。
  • 使用缓冲 IO 时需检查 scanner.Err() 以捕获可能的错误。

注意事项总结

  1. 结构体与方法:指针接收器适用于修改内容或避免拷贝,值接收器适合只读操作。
  2. 字符串与 Unicode:Go 原生支持 Unicode 编码,遍历和操作时应注意字符与字节的区别。
  3. 协程与通道:通道是协程通信的核心,需妥善管理通道的关闭和缓冲容量,避免死锁或资源竞争。
  4. 文件操作:使用 defer 确保文件资源被正确释放,避免文件句柄泄漏。
  5. JSON 标签规范:结构体字段必须导出,JSON 标签需匹配字段格式,注意类型一致性。

使用社交账号登录

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...