golang 小demo --- 一个需求如何实现成代码

// 需求------将TXT文件中的数据按照不同省市放进不同的省市文件中。
// 面向过程思路:创建34个文件,然后读取文件逐行将数据放进通道内,1协程从通道内读取数据,分析是属于哪个省市然后写入文件中。这个是面向过程的写法。
// 弊端:可能同时有两个协程共同写入一个文件 造成数据缺失
// 问题:1.如何判断是否读取结束,关闭协程,select 两个channel一个循环数据一个结束读取2.加锁防止两个协程同时写入每个文件
// 面向对象思路:创建34个文件,34个通道,然后读取文件逐行分析是哪个省市然后放进对应的通道中,(34个协程从34个通道中读取数据分析省市写入对应文件中,这么写和面向过程就一样了,没有意义)应该将通道和文件绑定在一个对象内,接收端一接收数据立即写入绑定的文件   还分析个屁呀
// 优点:34个协程一个文件一个协程  不会有两个协程写入一个文件的错误,
// 问题:1.如何判断这个省的协程是否结束 wg
// 面向思想主要是将文件和通道绑定  做结构体  将结构体作为参数传递
// 最后阻塞wg  和  关闭通道  总是忘记
 

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
	"sync"
)

type Provice struct {
	// 省份证前两位
	Id int
	// 省的名称
	Name string
	// 对应省的文件
	FileName *os.File
	// 对应省的通道
	ChanData chan string
}

var wg sync.WaitGroup

func main() {
	ps := []string{
		"北京11", "天津12", "河北13", "内蒙古15", "上海31", "湖北42", "湖南43",
		"广西45", "海南46", "四川51", "贵州52", "云南53", "西藏54", "重庆55",
		"陕西61", "甘肃62", "青海63", "宁夏64", "新疆65", "山西14", "辽宁21",
		"吉林22", "黑龙江23", "江苏32", "浙江33", "河南41", "澳门82", "台湾83",
		"香港81",
	}
	proviceMap := make(map[int]*Provice, 4096) // 这 里是指针 对象作为参数值 一般都是指针
	for _, v := range ps {
		name := v[:len(v)-2]
		idstr := v[len(v)-2:]
		id, _ := strconv.Atoi(idstr)
		provice := Provice{Id: id, Name: name}
		file, err := os.OpenFile("./info/"+name+".txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
		if err != nil {
			panic(name + "文件创建失败")
		}
		defer file.Close()
		provice.FileName = file
		provice.ChanData = make(chan string, 4096)
		proviceMap[id] = &provice
		fmt.Println(name + "对象创建完成")
	}
	// 创建34个协程 监听写入文件
	for _, v := range proviceMap {
		wg.Add(1)
		go wirteData(v)
	}
	// 开始读数据
	file, err := os.Open("info.txt")
	if err != nil {
		panic("打开文件错误")
	}
	defer file.Close()
	bufioReader := bufio.NewReader(file)
	for {
		line, _, err := bufioReader.ReadLine()
		if err == io.EOF {
			fmt.Println("读取原始文件数据完毕")
			// 读取完毕后  循环关闭通道
			for _, v := range proviceMap {
				close(v.ChanData)
			}
			break
		}
		lineStr := string(line) // 转化字符串
		fmt.Println(lineStr)
		lineArr := strings.Split(lineStr, ",") // 按,分割
		idstr := lineArr[1][0:2]
		id, _ := strconv.Atoi(idstr) // 获取第二个数组的前二位
		if provice, ok := proviceMap[id]; ok {
			provice.ChanData <- lineStr
		}
	}

	wg.Wait()
	fmt.Println("操作完毕")
}

// 写入数据
func wirteData(provice *Provice) {
	for data := range provice.ChanData {
		provice.FileName.Write([]byte(data + "\n"))
	}
	wg.Done()
	fmt.Println(provice.Name + "写入完毕")
}

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页