Golang 新手求助
帮朋友做 excel 的简单处理。原本是 python 栈,心想使用省事就像打包成 exe 文件,python 打包的 exe 文件又太大,而且会有各种奇奇怪怪的问题。刚好最近在学 golang,就用 golang 在写代码,不过遇到了 Goroutine 和 Channel 配合使用的问题。
问题的大致是这样的,先找出所有的符合条件的 Excel 文件,放入一个 chanfileChan中,然后通过读取这个 chan 中的数据,使用 Goroutine 调用utlis.ReadExcelFile的方法将传入的文件进行分析,只对需要的处理的行进行处理,并用一个 chanResultChan去接受,最后再将读取到的结果进行处理。但是对ResultChan进行处理之后就会报死锁的错误,我怎么样都不能定位到原因。请各位好哥哥帮帮我。 代码如下
main.go
package main import ( utils "excelmaker/src/Utils" "fmt" "log" "os" "path/filepath" "strings" "sync" ) func main() { pwd, _ := os.Getwd() // 找到本地路径 filenamePaths, err := filepath.Glob(filepath.Join(pwd, "*")) //获取本地目录下所有文件 if err != nil { log.Fatal(err) } fileChan := make(chan string, 5) for _, filePathName := range filenamePaths { fileExt := filepath.Ext(filePathName) fileName := filepath.Base(filePathName) if fileExt == ".xlsx" && strings.Contains(fileName, "工资表") { fmt.Println(filePathName) fileChan <- filePathName } } totalFileNum := len(fileChan) wg := sync.WaitGroup{} wg.Add(totalFileNum) for filePathName := range fileChan { go utils.ReadExcelFile(filePathName, &wg) } go utils.MakeTotalExcel() //会出现死锁 wg.Wait() }
Utils/utils.go
package utils import ( "fmt" "strconv" "strings" "sync" "github.com/360EntSecGroup-Skylar/excelize/v2" ) type ExcelData struct { Name string Salar int Company string } var ResultChan = make(chan *ExcelData, 10) const SalaryTable = "工资表" func ReadExcelFile(filePathName string, wg *sync.WaitGroup) { // func ReadExcelFile(filePathName string) { f, err := excelize.OpenFile(filePathName) if err != nil { fmt.Println(err) return } var company string if strings.Contains(filePathName, "头疗") { company = "头疗店" } else if strings.Contains(filePathName, "城东") { company = "城东店" } else if strings.Contains(filePathName, "熹 SPA") { company = "熹 SPA 店" } else if strings.Contains(filePathName, "置地") { company = "置地店" } else { company = "东方丽景店" } result, _ := f.SearchSheet(SalaryTable, "实发工资", false) salaryColIndex, _, _ := excelize.CellNameToCoordinates(result[0]) rows, err := f.Rows(SalaryTable) if err != nil { fmt.Println(err) return } for rows.Next() { row, err := rows.Columns() if err != nil { fmt.Println(err) return } if len(row) != 0 { var stringNotAnalysisList = []string{"", "姓名", "合计"} if ok, _ := Contain(row[0], stringNotAnalysisList); ok { continue } else { salary, _ := strconv.Atoi(row[salaryColIndex-1]) tempData := ExcelData{ Name: row[0], Salar: salary, Company: company, } ResultChan <- &tempData } } } wg.Done() } func MakeTotalExcel() { resultMap := make(map[string]map[string]int) companyList := []string{"姓名"} for v := range ResultChan { // fmt.Println(v.Name) if ok, _ := Contain(v.Name, resultMap); !ok { resultMap[v.Name] = make(map[string]int) } resultMap[v.Name][v.Company] = v.Salar if ok, _ := Contain(v.Company, companyList); !ok { companyList = append(companyList, v.Company) } } fmt.Println(companyList) fmt.Println(resultMap) }
Utils/commont_utils.go
package utils import ( "errors" "reflect" ) // 判断 obj 是否在 target 中,target 支持的类型 arrary,slice,map func Contain(obj interface{}, target interface{}) (bool, error) { targetValue := reflect.ValueOf(target) switch reflect.TypeOf(target).Kind() { case reflect.Slice, reflect.Array: for i := 0; i < targetValue.Len(); i++ { if targetValue.Index(i).Interface() == obj { return true, nil } } case reflect.Map: if targetValue.MapIndex(reflect.ValueOf(obj)).IsValid() { return true, nil } } return false, errors.New("not in array") }