Replace strings in file concurently in golang

Viewed 87

I've a huge text file containing some strings to be replaced and i want to do that in a concurrent way so that i'll be able to replace more than one string , here's my current code :

        import (
        "fmt"
        "io/ioutil"
        "os"
        "path/filepath"
        "strings"
        "sync"
    )
    
    
    var fileMutex sync.Mutex
    
   var (
    oldHelloWorld = "hel world"
    newHelloWorld = "hello world"
    oldJohnDoe    = "joh doe"
    newJohnDoe    = "John Doe"
    oldJaneDoe    = "jane doeee"
    newJaneDoe    = "Jane Doe"
    )
    
    var (
        changesHolder = map[string]string{
          oldHelloWorld: newHelloWorld,
          oldJohnDoe: newJohnDoe,
          oldJaneDoe: newJaneDoe,
        }
    )
    
    func doReplace(fileName,newContent string, wg *sync.WaitGroup)  {
    
        fileMutex.Lock()
        defer fileMutex.Unlock()
        defer wg.Done()
        err := ioutil.WriteFile(fileName, []byte(newContent), 0)
        if err != nil {
            panic(err)
        }
    }
    
    func replace(fileName string){
    
        var wg *sync.WaitGroup = new(sync.WaitGroup)
        read, err := ioutil.ReadFile(fileName)
        if err != nil {
            panic(err)
        }
    
        var newContent = ""
        for key, value := range changesHolder {
            wg.Add(1)
            newContent = strings.Replace(string(read), key, value, -1)
    
            go doReplace(fileName,newContent, wg)
        }
    
        wg.Wait()
    }
    
    func main() {
       replace("myText.txt")
    }

But the result is only the last changesHolder element (oldJaneDoe) which gets replaced although my text file contains all other occurrences. Any help is appreciated!

1 Answers

strings.Replace use StringBuilder, so it can't concurrent

you can write a byte replace function youself

follow is a example:

package main

import (
    "fmt"
    "sync"
)

var wg sync.WaitGroup

var (
    changesHolder = map[byte]byte{
        'a': '1',
        'b': '2',
        'c': '3',
    }
)

func Replace(bs []byte, old byte, new byte) {
    for i, b := range bs {
        if b == old {
            bs[i] = new
        }
    }
    wg.Done()
}

func main() {
    b := []byte("aa bb cc")
    for old, new := range changesHolder {
        wg.Add(1)
        go Replace(b, old, new)
    }
    wg.Wait()
    fmt.Printf("%s\n", b)
}
Related