一.同时向管道读写数据
package main
import "fmt"
func main() {
writeChan := make(chan int, 20) // 写入通道,缓冲大小为20
exitChan := make(chan bool) // 退出通道
go readData(writeChan, exitChan) // 启动readData协程
go writeData(writeChan) // 启动writeData协程
for {
v, ok := <-exitChan // 接收退出通道值
if ok {
fmt.Println("完成:", v) // 打印完成信息
break // 退出循环
}
}
}
func writeData(writeChan chan int) {
for i := 1; i <= 20; i++ {
writeChan <- i // 将i写入通道
fmt.Println("写入数据~~:", i) // 打印写入数据信息
}
close(writeChan) // 关闭通道
}
func readData(writeChan chan int, exitChan chan bool) {
for v := range writeChan {
fmt.Println("读取数据~~:", v) // 打印读取数据信息
}
// 结束
exitChan <- true // 向退出通道发送完成信号
close(exitChan) // 关闭通道
}
二.协程案例-计算2000个数各个数的累加和
package main
import (
"fmt"
"sync"
)
var (
wg3 sync.WaitGroup // wg3用于等待PutData函数执行完成
wg4 sync.WaitGroup // wg4用于等待SumUp函数执行完成
)
func main() {
numChan := make(chan int, 2000) // 创建一个缓冲大小为2000的整型通道
wg3.Add(2000) // 将等待计数器设置为2000
go PutData(numChan) // 启动PutData协程,向numChan通道写入数据
wg3.Wait() // 等待PutData协程执行完成
close(numChan) // 关闭numChan通道
fmt.Println("num:", len(numChan)) // 打印numChan通道内的数据个数(应为2000)
wg4.Add(2000) // 将等待计数器设置为2000
resChan := make(chan map[int]int, 2000) // 创建一个缓冲大小为2000的映射整型到映射整型的通道
for n := range numChan {
go SumUp(n, resChan) // 启动SumUp协程,计算numChan中的每个数字的累加和并存储到resChan通道
}
wg4.Wait() // 等待所有SumUp协程执行完成
close(resChan) // 关闭resChan通道
fmt.Println("res:", len(resChan)) // 打印resChan通道内的数据个数(应为2000)
for res := range resChan {
for key, val := range res {
fmt.Printf("res[%v]=%v\n", key, val) // 遍历输出resChan通道中的结果
}
}
}
// SumUp 计算累加和
func SumUp(n int, resChan chan map[int]int) {
sumMap := make(map[int]int) // 创建一个整型到整型的映射
res := 0 // 初始化res为0
for i := 1; i <= n; i++ {
res += i // 将i累加到res上
}
sumMap[n] = res // 将res存储到sumMap中对应的n位置
resChan <- sumMap // 将sumMap发送到resChan通道
defer wg4.Done() // 在协程结束时,将等待计数器减1
}
func PutData(numChan chan int) {
for i := 1; i <= 2000; i++ {
numChan <- i // 将i发送到numChan通道
wg3.Done() // 等待发送完成后,将等待计数器减1
}
}
三.生产1000个数据保存文件,读取文件排序后另存文件
package main
import (
"bufio"
"fmt"
"io"
"math/rand"
"os"
"strconv"
"strings"
"sync"
"time"
)
var (
wg5 sync.WaitGroup // wg5用于等待所有goroutine完成
)
// goroutine+channel实现写入文件和排序
func main() {
wg5.Add(1000) // 增加1000个等待的goroutine
go writeDataToFile() // 启动写入数据到文件的goroutine
wg5.Wait() // 等待所有goroutine完成
fmt.Println("文件写入完成!!!!!!!!!!")
fmt.Println()
fmt.Println("读取所写文件对其排序生成新的文件!!!!!!!")
dataChan := make(chan int, 1000) // 创建一个容量为1000的整型通道
readDataToChannel(dataChan) // 启动读取数据到通道的goroutine
sortToSave(dataChan) // 对通道中的数据进行排序和保存
}
// 将数据放入切片 对切片排序 再写入文件保存
func sortToSave(dataChan chan int) {
dataSlice := make([]int, len(dataChan)) // 创建一个与通道长度相同的切片
for i := 0; i < len(dataSlice); i++ {
for data := range dataChan { // 从通道中接收数据
dataSlice[i] = data
break
}
}
fmt.Println(len(dataSlice)) // 打印切片长度, 为1000
QuickSort(dataSlice) // 使用快速排序
fmt.Println("排序后:", dataSlice)
file, err := os.OpenFile("d:/go-test/sortData.txt", os.O_WRONLY|os.O_TRUNC|os.O_APPEND|os.O_CREATE, 0666) // 打开或创建文件
if err != nil {
fmt.Println("open file err ", err)
return
}
defer file.Close() // 函数返回前关闭文件
writer := bufio.NewWriter(file) // 创建写入器
for i := 0; i < len(dataSlice); i++ {
_, err := writer.WriteString(strconv.Itoa(dataSlice[i]) + ",") // 将切片中的数据写入文件
if err != nil {
fmt.Println("write file err ", err)
break
}
}
writer.Flush() // 刷新写入器
fmt.Println("有序文件写入完成!!!!!")
}
// 随机生产1000个数据写入文件
func writeDataToFile() {
rand.Seed(time.Now().UnixNano()) // 使用当前时间作为随机数种子
file, err := os.OpenFile("d:/go-test/data.txt", os.O_WRONLY|os.O_TRUNC|os.O_APPEND|os.O_CREATE, 0666) // 打开或创建文件
if err != nil {
fmt.Println("open file err ", err)
return
}
defer file.Close() // 函数返回前关闭文件
writer := bufio.NewWriter(file) // 创建写入器
for i := 0; i < 1000; i++ {
_, err := writer.WriteString(strconv.Itoa(rand.Intn(1000)+1) + ",") // 随机生成1000个数据并写入文件
wg5.Done() // wg5计数减1
if err != nil {
fmt.Println("write file err ", err)
break
}
}
writer.Flush() // 刷新写入器
}
// 从文件中读取数据到通道
func readDataToChannel(dataChan chan int) {
file, err := os.Open("d:/go-test/data.txt") // 打开文件
if err != nil {
fmt.Println("open file err ", err)
return
}
defer file.Close() // 函数返回前关闭文件
reader := bufio.NewReader(file) // 创建读取器
for {
dataStr, errRead := reader.ReadString(',') // 从文件中读取数据直到文件末尾或发生错误
if errRead != nil {
if errRead == io.EOF {
fmt.Println("读取结束!!!!")
} else {
fmt.Println("读取错误:", errRead)
}
break
}
atoi, _ := strconv.Atoi(strings.Trim(dataStr, ",")) // 将字符串转换为整数
dataChan <- atoi // 将整数发送到通道
}
close(dataChan) // 在写入所有数据后关闭通道
fmt.Println("长度:", len(dataChan)) // 打印通道长度, 为1000
}
// QuickSort 快速排序
func QuickSort(arr []int) {
// 结束条件
if len(arr) < 2 {
return
}
left, right := 0, len(arr)-1 // 定义分区点的左右指针
pivot := right // 将分区点设置为数组的最后一个元素
for i := 0; i < len(arr); i++ {
if arr[i] < arr[pivot] {
arr[left], arr[i] = arr[i], arr[left] // 将较小的元素交换到左边
left++
}
}
arr[left], arr[right] = arr[right], arr[left] // 将分区点交换到中间
QuickSort(arr[:left]) // 对分区点左边的子数组进行递归排序
QuickSort(arr[left+1:]) // 对分区点右边的子数组进行递归排序
}
文章来源地址https://www.toymoban.com/news/detail-806137.html
文章来源:https://www.toymoban.com/news/detail-806137.html
到了这里,关于go的协程和管道运用案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!