Просмотр исходного кода

Fixed the datarace surrounding the channel. This was done by moving the
channel close to the writer goroutine (as is idiomatic). readSheetFromFile
now returns an error to stop the writer routine from trying to read more
sheets if one contains an error (this will prevent goroutines from
leaking due to readers that stop reading on receiving an error).

Neoin 8 лет назад
Родитель
Сommit
fc46433220
1 измененных файлов с 9 добавлено и 4 удалено
  1. 9 4
      lib.go

+ 9 - 4
lib.go

@@ -646,13 +646,15 @@ func readSheetViews(xSheetViews xlsxSheetViews) []SheetView {
 // into a Sheet struct.  This work can be done in parallel and so
 // into a Sheet struct.  This work can be done in parallel and so
 // readSheetsFromZipFile will spawn an instance of this function per
 // readSheetsFromZipFile will spawn an instance of this function per
 // sheet and get the results back on the provided channel.
 // sheet and get the results back on the provided channel.
-func readSheetFromFile(sc chan *indexedSheet, index int, rsheet xlsxSheet, fi *File, sheetXMLMap map[string]string) {
+func readSheetFromFile(sc chan *indexedSheet, index int, rsheet xlsxSheet, fi *File, sheetXMLMap map[string]string) (errRes error) {
 	result := &indexedSheet{Index: index, Sheet: nil, Error: nil}
 	result := &indexedSheet{Index: index, Sheet: nil, Error: nil}
 	defer func() {
 	defer func() {
 		if e := recover(); e != nil {
 		if e := recover(); e != nil {
+
 			switch e.(type) {
 			switch e.(type) {
 			case error:
 			case error:
 				result.Error = e.(error)
 				result.Error = e.(error)
+				errRes = e.(error)
 			default:
 			default:
 				result.Error = errors.New("unexpected error")
 				result.Error = errors.New("unexpected error")
 			}
 			}
@@ -665,7 +667,7 @@ func readSheetFromFile(sc chan *indexedSheet, index int, rsheet xlsxSheet, fi *F
 	if error != nil {
 	if error != nil {
 		result.Error = error
 		result.Error = error
 		sc <- result
 		sc <- result
-		return
+		return error
 	}
 	}
 	sheet := new(Sheet)
 	sheet := new(Sheet)
 	sheet.File = fi
 	sheet.File = fi
@@ -680,6 +682,7 @@ func readSheetFromFile(sc chan *indexedSheet, index int, rsheet xlsxSheet, fi *F
 
 
 	result.Sheet = sheet
 	result.Sheet = sheet
 	sc <- result
 	sc <- result
+	return nil
 }
 }
 
 
 // readSheetsFromZipFile is an internal helper function that loops
 // readSheetsFromZipFile is an internal helper function that loops
@@ -719,12 +722,14 @@ func readSheetsFromZipFile(f *zip.File, file *File, sheetXMLMap map[string]strin
 	sheetsByName := make(map[string]*Sheet, sheetCount)
 	sheetsByName := make(map[string]*Sheet, sheetCount)
 	sheets := make([]*Sheet, sheetCount)
 	sheets := make([]*Sheet, sheetCount)
 	sheetChan := make(chan *indexedSheet, sheetCount)
 	sheetChan := make(chan *indexedSheet, sheetCount)
-	defer close(sheetChan)
 
 
 	go func() {
 	go func() {
+		defer close(sheetChan)
 		err = nil
 		err = nil
 		for i, rawsheet := range workbookSheets {
 		for i, rawsheet := range workbookSheets {
-			readSheetFromFile(sheetChan, i, rawsheet, file, sheetXMLMap)
+			if err := readSheetFromFile(sheetChan, i, rawsheet, file, sheetXMLMap); err != nil {
+				return
+			}
 		}
 		}
 	}()
 	}()