1
\$\begingroup\$

Below is a piece of code that is responsible for serializing files. ZL_LIST and PERS_LIST are XML file structs, I have not shown them here to save space.

Please check my code.

package parser import ( "encoding/xml" "fmt" "golang.org/x/text/encoding/charmap" "io" "io/ioutil" "os" "path/filepath" "sync" ) type Files struct { Name string PathZipFile string PathUnzipFile string } type nameMap map[string]bool func (ZL_LIST) Parse(FilesName []*Files) { unzipPath, err := filepath.Abs("tmp") files, err := ioutil.ReadDir(unzipPath) f := make([]*Files, 0) for _, file := range files { fileZip := new(Files) if !file.IsDir() && file.Name()[:1] != "." { fileZip.Name = file.Name() fileZip.PathUnzipFile = filepath.Join(unzipPath, file.Name()) f = append(f, fileZip) } } if err != nil { fmt.Printf("[ERROR] Error retrieving files %v", err) } names := make(nameMap, 1) var wg sync.WaitGroup var countHmLmFiles int = -1 var countHmFiles int = 0 var countLmFiles int = 0 var file *Files for countHmLmFiles, file = range f { wg.Add(1) go func(filename *Files) { parseHmLm(filename, &countHmFiles, &countLmFiles, &names) wg.Done() }(file) } wg.Wait() fmt.Printf("[INFO] Read %d files from them HM files %d and LM files %d ", countHmLmFiles+1, countHmFiles, countLmFiles) } func parseHmLm(filename *Files, countHmFiles *int, countLmFiles *int, names *nameMap) { fmt.Println("[INFO] считывается файл ", filename.Name, " с заголовком ", filename.Name[:2]) xmlFile, err := os.Open(filepath.Join(filename.PathUnzipFile)) if err != nil { fmt.Printf("[ERROR] Cannot open file %e \n", err) } defer xmlFile.Close() switch filename.Name[:2] { case "HM": (*names)[filename.Name] = true (*countHmFiles) += 1 var hFile ZL_LIST decoder := xml.NewDecoder(xmlFile) decoder.CharsetReader = charset err := decoder.Decode(&hFile) if err != nil { fmt.Errorf("[ERROR] Cannot decode file %e", err) } case "LM": (*countLmFiles) += 1 var lFile PERS_LIST decoder := xml.NewDecoder(xmlFile) decoder.CharsetReader = charset err := decoder.Decode(&lFile) if err != nil { fmt.Errorf("[ERROR] Cannot decode file %e", err) } } } func charset(charset string, input io.Reader) (io.Reader, error) { switch charset { case "windows-1251": return charmap.Windows1251.NewDecoder().Reader(input), nil default: return nil, fmt.Errorf("unknown charset: %s", charset) } } 

Calling function

package api import ( "net/http" "github.com/go-chi/render" "../../store/parser" "fmt" "path/filepath" ) func (s *Rest) parse(w http.ResponseWriter, r *http.Request) { uploadPath, err := filepath.Abs("./upload/") if err != nil { fmt.Printf("[ERROR] can not find the specified path %e", err) } unzipPath, err := filepath.Abs("./tmp") if err != nil { fmt.Printf("[ERROR] can not find the specified path %e", err) } p := parser.Files{} filesName := p.GetFileName(uploadPath, unzipPath) p.UnzipFiles(filesName, unzipPath) ... ... 
\$\endgroup\$

    1 Answer 1

    2
    \$\begingroup\$

    Variables

    Go has two ways of declaring new variables: a var notation and a short one. It's preferable to use the short one:

    wg := sync.WaitGroup{} countHmLmFiles := -1 countHmFiles := 0 countLmFiles := 0 

    Also when declaring lots of global variables in the package block you may use block notation:

    var ( a int = 1 b string = "foo" ) 

    You can declare variables directly in the for loop:

    for countHmLmFiles, file := range f { // countHmLmFiles and file will be visible only here } 

    This way their scope will be limited to for body.

    Maps in Go

    You've created a map with make:

    names := make(nameMap, 1) 

    I don't see a point in creating a map for a single element. Also when you don't need the size argument in make you may simply write names := nameMap{}.

    No need pass maps with pointer. Maps and slices are already a reference type and may be passed directly by value. It won't issue a full copy.

    Error handling

    You've missed lots of error checks. Ideally every error must be handled in place. Otherwise use _ to ignore it and make a comment to be specific on this as it looks like a broken code.

    The switch lacks the default case. It worth adding it to catch other possible values of filename.Name[:2].

    Also don't forget to add terminating \n to fmt.Printf to separate log messages.

    \$\endgroup\$

      Start asking to get answers

      Find the answer to your question by asking.

      Ask question

      Explore related questions

      See similar questions with these tags.