Go语言 协程配合管道的综合案例-2

package main

import (
	"bufio"
	"math/rand"
	"os"
	"sort"
	"strconv"
	"time"
)

func main() {

	//初始化一个种子用来生成随机数据
	rand.Seed(time.Now().UnixNano())

	//文件写入状态
	writerChanOk := make(chan<- bool, 10)

	//1.开一个协程writeDataTofile,随机生成1000个数据,存放到文件中
	pathNameBefore := "d:/writeDataFile_" //在D盘根目录生成一个文件名以writeDataFile_开头的文件
	pathNameRear := ".txt"                //文件后缀

	for i := 0; i < 10; i++ {
		//开启十个协程
		go func(pathNameLeft, pathNameRight string, i int, writerChanOk chan<- bool) {
			file, err := os.OpenFile(pathNameLeft+strconv.Itoa(i)+pathNameRight, os.O_CREATE|os.O_TRUNC, 0777)
			if err != nil {
				panic(err)
			}
			defer file.Close()
			writer := bufio.NewWriter(file)
			for i := 0; i < 1000; i++ {
				//往文件写入指定范围随机字符数据
				writer.WriteString(string(rand.Int63n('z'-'A') + 'A'))
			}
			writer.Flush()
			//写入文件 完成一次 状态
			writerChanOk <- true
		}(pathNameBefore, pathNameRear, i, writerChanOk)
	}

	for {
		//判断协程是否写入完成
		if len(writerChanOk) == 10 {
			//关闭文件写入状态管道
			close(writerChanOk)
			break
		}
	}

	//数据管道
	dataChan := make(chan string, 10)
	//协程完成状态
	appear := make(chan<- bool, 10)

	//2.当writeDataFile完成写1000个数据到文件后,让sort协程从文件中读取1000个数据并排序,
	//3.考察点:协程和管道+文件的综合使用
	for i := 0; i < 10; i++ {
		go func(pathNameLeft, pathNameRight string, i int, dataChan chan string, appear chan<- bool) {
			file, err := os.OpenFile(pathNameLeft+strconv.Itoa(i)+pathNameRight, os.O_RDONLY, 0777)
			if err != nil {
				panic(err)
			}
			defer file.Close()
			//创建一个Int切片用于排序
			intSlice := &[]int{}
			reader := bufio.NewReader(file)
			for j := 0; j < 1000; j++ {
				data, _ := reader.ReadByte()
				//循环读取一千个字节并存入Int切片
				*intSlice = append(*intSlice, int(data))
			}
			//排序
			sort.Ints(*intSlice)
			str := ""
			for j := 0; j < len(*intSlice); j++ {
				//转为字符串
				str += string(byte((*intSlice)[j]))
			}
			//字符串数据存入管道
			dataChan <- str
			appear <- true
		}(pathNameBefore, pathNameRear, i, dataChan, appear)
	}

	go func() {
		for {
			//判断协程是否完成任务
			if len(appear) == 10 {
				//关闭数据管道
				close(dataChan)
				close(appear)
				break
			}
		}
	}()

	//重新写入文件状态
	writeStatus := make(chan<- bool, 10)

	//4.功能拓展开10个协程writeDataTofile,每隔协程随机生成1000个数据,存放到10个文件
	//5.当10个文件都生成了,让10个sort协程从10文件中读取1000个数据,并完成排序重新写入到10个结果文件。
	i := 0
	for v := range dataChan {
		go func(pathNameLeft, pathNameRight string, i int, writeStatus chan<- bool) {
			file, err := os.OpenFile(pathNameLeft+strconv.Itoa(i)+pathNameRight, os.O_CREATE|os.O_APPEND, 0777)
			if err != nil {
				panic(err)
			}
			defer file.Close()
			writer := bufio.NewWriter(file)
			//原要求是让覆盖重新写入,这里改为追加
			writer.WriteString("\n" + v)
			writer.Flush()
			writeStatus <- true
		}(pathNameBefore, pathNameRear, i, writeStatus)
		i++
	}
	for {
		if len(writeStatus) == 10 {
			break
		}
	}
}

运行效果

Go语言 协程配合管道的综合案例-2
Go语言 协程配合管道的综合案例-2

上一篇:GO语言信道(channel)--几种死锁情况


下一篇:一文读透GO语言的通道