1

I have a slightly funky issue in golang. Essentially I have a slice of strings which represent file paths. I then run a cat against those filepaths to combine the files before sorting, deduping, etc.

here is the section of code (where 'applicableReductions' is the string slice):

    applicableReductions := []string{}

    for _, fqFromListName := range fqFromListNames {
         filePath := GetFilePath()
         //BROKE CODE GOES HERE
    }
    applicableReductions = append(applicableReductions, filePath)

    fileOut, err := os.Create(toListWriteTmpFilePath)
    if err != nil {
        return err
    }
    cat := exec.Command("cat", applicableReductions...)
    catStdOut, err := cat.StdoutPipe()
    if err != nil {
        return err
    }
    go func(cat *exec.Cmd) error {
        if err := cat.Start(); err != nil {
            return fmt.Errorf("File reduction error (cat) : %s", err)
        }
        return nil
    }(cat)

    // Init Writer & write file
    writer := bufio.NewWriter(fileOut)
    defer writer.Flush()

    _, err = io.Copy(writer, catStdOut)
    if err != nil {
        return err
    }

    if err = cat.Wait(); err != nil {
        return err
    }

    fDiff.StandardiseData(fileOut, toListUpdateFolderPath, list.Name)

The above works fine. The problem comes when I try to append a new ele to the array. I have a seperate function which creates a new file from db content which is then added to the applicableReductions slice.

func RetrieveDomainsFromDB(collection *Collection, listName, outputPath string) error {
    domains, err := domainReviews.GetDomainsForList(listName)
    if err != nil {
        return err
    }

    if len(domains) < 1 {
        return ErrNoDomainReviewsForList
    }

    fh, err := os.OpenFile(outputPath, os.O_RDWR, 0774)
    if err != nil {
        fh, err = os.Create(outputPath)
        if err != nil {
            return err
        }
    }
    defer fh.Close()
    _, err = fh.WriteString(strings.Join(domains, "\n"))
    if err != nil {
        return err
    }

    return nil
}

If I call the above function and append the filePath to the applicableReduction slice, it is in there but doesnt get called by cat.

To clarify, when I put the following where it says BROKE CODE GOES HERE:

    if dbSource {
        err = r.RetrieveDomainsFromDB(collection, ToListName, filePath)
        if err != nil {
                return err
                continue
            }
      }

The filepath can be seen when doing fmt.Println(applicableReductions) but the content of the files contents are not seen in the cat output file.

I thought perhaps a delay in the file being written so i tried adding a time.wait, tis didnt help. However the solution I found was to sort the slice, e.g this code above the call to exec cat solves the problem but I dont know why:

sort.Strings(applicableReductions)

I have confirmed all files present on both successful and unsucessful runs the only difference is without the sort, the content of the final appended file is missing

An explanation from a go-pro out there would be very much appreciated, let me know if you need more info, debug - happy to oblige to understand

UPDATE It has been suggested that this is the same issue as here: Golang append an item to a slice, I think I understand the issue there and I'm not saying this isnt the same but I cannot see the same thing happenning - the slice in question is not touched from outside the main function (e.g. no editing of the slice in RetrieveDomainsFromDB function), I create the slice before a loop, append to it within a loop and then use it after the loop - Ive added an example at the top to show how the slice is built - please could someone clarify where this slice is being copied if this is the case

Community
  • 1
  • 1
SwiftD
  • 5,769
  • 6
  • 43
  • 67
  • Possible duplicate of [Golang append an item to a slice](http://stackoverflow.com/questions/20195296/golang-append-an-item-to-a-slice) – Charlie Tumahai Apr 29 '16 at 17:30
  • sort will also not solve the problem actually. May be you are lucky that some of the elements are moved ahead of the underlying array of the slice(because of sort) and hence the files get processed. The slice passed to the go routine will be having the same length, start-position in the underlying array etc. irrespective of of what is appended to it from some other functions. – Nipun Talukdar Apr 29 '16 at 17:58
  • Here is an example demonstrating the behavior of slices https://play.golang.org/p/kZGovImZDm .... May be you should pass the new file paths through a channel to the goroutine. – Nipun Talukdar Apr 29 '16 at 18:10
  • Im not saying that its not the same as referenced question but I dont see it. I fully create and assign all elements to the slice within the same function - the slice is assigned completely before being passed to exec within goroutine. I cannot see where this is being copied - Could someone please clarify – SwiftD May 09 '16 at 10:27

1 Answers1

0

UPDATE AND CLOSE Please close question - the issue was unrelated to the use of a string slice. Turns out that I was reading from the final output file before bufio-writer had been flushed (at end of function before defer flush kicked in on function return)

I think the sorting was just re-arranging the problem so I didnt notice it persisted or possibly giving some time for the buffer to flush. Either way sorted now with a manual call to flush.

Thanks for all help provided

SwiftD
  • 5,769
  • 6
  • 43
  • 67