Go 语言入门指南:基础语法和常用特性解析(下) | 青训营

在上一篇文章Go 语言入门指南:基础语法和常用特性解析(上)中,我总结了与Go语言相关的安装和设置、基础语法等知识点,今天的文章中我们将继续介绍Go语言的复合数据类型和并发编程相关的知识~

3. 复合数据类型

在Go语言中,复合数据类型允许你将多个值组合在一起,以创建更为复杂和结构化的数据结构。本部分将介绍Go语言中的几种重要的复合数据类型,包括数组、切片、映射(Map)和结构体(Struct)。

3.1. 数组

  • 数组是一种固定长度、相同数据类型元素的集合。
  • 声明数组:var arr [n]T,其中 n 为数组长度,T 为元素类型。
  • 初始化数组:arr := [n]T{val1, val2, ...}
  • 访问数组元素:使用索引访问,索引从 0 开始。

与多数传统语言一样,Go语言的数组在功能使用上相差不大,唯一注意的是其变量定义遵循Go语言自己的定义风格,即数据类型后置 。同时,使用len()方法可以获取数组长度。

less 复制代码
var arr [10]int
​
arr[0] = 1123
arr[1] = 5813
​
fmt.Println(arr[1], len(arr)) // 5813 2

3.2. 切片

  • 切片是动态长度、指向数组的引用,类似于动态数组。
  • 创建切片:slice := make([]T, length, capacity),其中length 为初始长度,capacity 为底层数组容量。
  • 切片操作:可以使用 slice[start:end] 对切片进行切割。
  • 切片扩容:通过 append 函数将元素添加到切片。

而对于切片,其为Go语言特有的类型,可以类比为动态数组,即声明时不指定大小。

go 复制代码
arr := make([]int, 3)
arr[0] = 1
arr[1] = 1
arr[2] = 2
fmt.Println(arr[1], len(arr)) // 1 3
​
//append()追加数据至切片
arr = append(arr, 3)
arr = append(arr, 5, 8)
fmt.Println(arr)      // [1 1 2 3 5 8]
​
//copy()复制切片
arr2 := make([]int, len(arr))
copy(arr2, arr)
fmt.Println(arr2)     // [1 1 2 3 5 8]
​
//类似Python的切片语法
fmt.Println(arr[2:5]) // [2 3 5]
fmt.Println(arr[:5])  // [1 1 2 3 5]
fmt.Println(arr[2:])  // [2 3 5 8]

3.3. 映射

  • 创建映射:m := make(map[K]V),其中 K 为键的类型,V 为值的类型。
  • 插入和访问元素:m[key] = valuevalue = m[key]
  • 删除元素:delete(m, key)

Map 是一种无序的键值对 的集合,通过 key 来快速检索数据。

go 复制代码
// 创建一个初始容量为 10 的 Map
m := make(map[string]int, 10)
​
// 使用字面量创建 Map
m = map[string]int{
    "apple" : 1,
    "banana" : 2,
    "orange" : 3
}
​
// 获取键值对
vl := m["apple"]
v2, ok := m["pear"]
// 如果键不存在,ok 的值为 false,v2 的值为该类型的零值
​
// 修改键值对
m["apple"] = 5
​
// 获取map长度
len_m := len(m)
​
// 删除键值对
delete(m, "banana")

3.4. 结构体

  • 声明结构体:type StructName struct { field1 type1; field2 type2; ... }
  • 创建结构体实例:instance := StructName { field1: val1, field2: val2, ... }
  • 访问结构体字段:使用 instance.field

与其他的语言类似,Go语言中的结构体仍然是不同数据类型的字段的集合,用于表示一个更复杂的数据结构,其用法和其他语言相差不大。

go 复制代码
type Books struct {
    tilte string
    author string
    subject string
    bookid int
}
​
// 声明 book1 为 Books 类型
var book1 Books 
​
// book1 各参数赋值
book1.title = "Hello, Go!"
book1.author = "张三"
book1.subject = "IT"
book1.bookid = 123456

4. 并发编程

并发是指在同一时间内处理多个任务的能力,Go语言以其独特的并发模型在编写并发程序时具有明显优势。本部分将深入介绍Go语言中的并发编程,包括Goroutine、通道(Channel)和并发模式等内容。

4.1. Goroutine

  • Goroutine 是Go语言的轻量级线程,由Go运行时管理。
  • 使用关键字 go 启动一个Goroutine,将函数调用包装为并发任务。
  • Goroutine 之间共享内存,但通常通过通道进行通信,避免竞态条件。

Goroutine 是 Go 语言中的轻量级并发执行单元,是其并发模型的核心组成部分。Goroutine 使得在同一个程序中同时执行多个任务变得更加容易和高效,而且在语言层面上提供了内置的支持。

Goroutine 的创建和销毁开销非常小,相较于操作系统线程来说,创建数千甚至数百万个 Goroutine 是可行的。

同时,在 Go 程序中,你可以同时启动多个 Goroutine,它们将会并发地执行,不需要手动管理线程池或任务队列。

以下是一个使用 Goroutine 的简单示例,计算 1 到 10 的阶乘并打印结果:

go 复制代码
package main
​
import (
    "fmt"
)
​
func factorial(n int, ch chan int) {
    result := 1
    for i := 1; i <= n; i++ {
        result *= i
    }
    ch <- result
}
​
func main() {
    ch := make(chan int)
    for i := 1; i <= 10; i++ {
        go factorial(i, ch)
    }
    for i := 1; i <= 10; i++ {
        result := <-ch
        fmt.Printf("Factorial of %d: %d\n", i, result)
    }
}

通过使用 Goroutine,Go 语言能够以高效、简洁的方式实现并发,充分利用多核处理器的能力,从而提升程序性能和响应能力。然而,需要注意正确地处理 Goroutine 之间的同步和通信,以避免竞态条件和数据访问问题。

4.2. 通道(Channel)

  • 通道是Goroutine之间进行通信和同步的机制。
  • 使用 make 函数创建通道:ch := make(chan T)T 为通道中传递的数据类型。
  • 发送数据到通道:ch <- data。发送操作会阻塞,直到通道有足够的空间来存储数据。
  • 从通道接收数据:data := <-ch。接收操作会阻塞,直到通道中有数据可供接收。
  • 通道也支持带缓冲的通道:ch := make(chan T, capacity)

通道(Channel) 是 Go 语言中用于实现并发安全的数据传递和通信的机制。通道可以在 Goroutine 之间传递数据,并且能够在数据传递的同时进行同步操作,从而有效地避免了竞态条件和其他并发问题。

默认情况下,通道的发送和接收操作都是阻塞的,直到有一方准备好。

通过使用 select 语句可以实现非阻塞的通道操作,从而避免 Goroutine 阻塞在通道操作上。

通道适用于多个 Goroutine 之间的数据传递和同步,比如任务队列、消息传递等场景。

以下是一个简单的示例,演示了如何使用通道来计算两个数的和:

go 复制代码
package main
​
import (
    "fmt"
)
​
func add(a, b int, ch chan int) {
    sum := a + b
    ch <- sum
}
​
func main() {
    ch := make(chan int)
    go add(3, 5, ch)
    result := <-ch
    fmt.Println("Result:", result)
}

4.3. 并发模式

  • 基于通道的并发模式:使用通道在Goroutine之间传递数据,实现数据同步和任务协调。
  • 扇出-扇入模式:将一个输入通道分发到多个处理Goroutine,然后将结果合并到一个输出通道。
  • 选择器模式:使用 select 语句监听多个通道,响应可读或可写的通道操作。
  • 互斥锁和条件变量:通过 sync 包实现对共享资源的互斥访问和条件同步。
  • 工作池模式:工作池维护一组 Goroutine,用于执行特定的任务。
  • 串行模式:使用通道将多个 Goroutine 串行化,确保它们按顺序执行。

并发模式是一组在并发编程中常用的设计模式,用于解决在多个并发执行的 Goroutine 之间协调、同步和通信的问题。这些模式帮助开发者编写出更可靠、高效的并发程序,避免竞态条件、死锁和其他并发问题。

这些并发模式帮助开发者解决了在并发编程中常见的问题,使得并发程序更易于理解、维护和调试。根据不同的应用场景,开发者可以选择合适的模式来组织并发代码,从而充分利用多核处理器的能力,提高程序性能和响应能力。

相关推荐
CallBack8 个月前
Typora+PicGo+阿里云OSS搭建个人图床,纵享丝滑!
前端·青训营笔记
Taonce1 年前
站在Android开发者的角度认识MQTT - 源码篇
android·青训营笔记
AB_IN1 年前
打开抖音会发生什么 | 青训营
青训营笔记
monster1231 年前
结营感受(go) | 青训营
青训营笔记
翼同学1 年前
实践记录:使用Bcrypt进行密码安全性保护和验证 | 青训营
青训营笔记
hu1hu_1 年前
Git 的正确使用姿势与最佳实践(1) | 青训营
青训营笔记
星曈1 年前
详解前端框架中的设计模式 | 青训营
青训营笔记
tuxiaobei1 年前
文件上传漏洞 Upload-lab 实践(中)| 青训营
青训营笔记
yibao1 年前
高质量编程与性能调优实战 | 青训营
青训营笔记
小金先生SG1 年前
阿里云对象存储OSS使用| 青训营
青训营笔记