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)
 ...
 ...
sineemore
1,79512 silver badges33 bronze badges
asked Jul 11, 2018 at 6:21
\$\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.

answered Aug 15, 2018 at 8:51
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.