1

Execute a go method in another process where the main process might exit out, but child process should complete execution.

I was going through goroutines where I can execute methods concurrently, but the method stops execution once the main process exits.

func f() {
    time.Sleep(15 * time.Second)

    d1 := []byte("hello\ngo\n")
    err := ioutil.WriteFile("test", d1, 0644)
    if err != nil {
        fmt.Println(err.Error())
    }

    file, err := os.Create("test")
    if err != nil {
        fmt.Println(err.Error())
    }

    defer file.Close()

    d2 := []byte{115, 111, 109, 101, 10}
    n2, err := file.Write(d2)
    if err != nil {
        fmt.Println(err.Error())
    }

    fmt.Printf("wrote %d bytes\n", n2)

}

func main() {
    go f()

    fmt.Println("done")
} 

In the above function F, there is a sleep of 15 seconds. I want my main to exit out but my function f should run in background and finish the file creation. Is there any way we can achieve that without using os.exec().

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
akshay
  • 93
  • 1
  • 9

3 Answers3

1

You may use sync.WaitGroup like so:

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(1)
    go f(&wg)

    // go do another jobs here ...

    wg.Wait()
    fmt.Println("done")
}

func f(wg *sync.WaitGroup) {
    defer wg.Done()
    time.Sleep(1 * time.Second)

    d1 := []byte("hello\ngo\n")
    err := ioutil.WriteFile("test", d1, 0644)
    if err != nil {
        fmt.Println(err.Error())
    }

    f, err := os.Create("test")
    if err != nil {
        fmt.Println(err.Error())
    }

    defer f.Close()

    d2 := []byte{115, 111, 109, 101, 10}
    n2, err := f.Write(d2)
    if err != nil {
        fmt.Println(err.Error())
    }

    fmt.Printf("wrote %d bytes\n", n2)
}



You may use empty done channel chan struct{}, like so:

package main

import (
    "fmt"
    "io/ioutil"
    "os"
    "time"
)

func main() {
    done := make(chan struct{})
    go f(done)
    // go do another jobs here ...
    <-done
    fmt.Println("done")
}

func f(done chan struct{}) {
    defer func() { done <- struct{}{} }()
    time.Sleep(1 * time.Second)

    d1 := []byte("hello\ngo\n")
    err := ioutil.WriteFile("test", d1, 0644)
    if err != nil {
        fmt.Println(err.Error())
    }

    f, err := os.Create("test")
    if err != nil {
        fmt.Println(err.Error())
    }

    defer f.Close()

    d2 := []byte{115, 111, 109, 101, 10}
    n2, err := f.Write(d2)
    if err != nil {
        fmt.Println(err.Error())
    }

    fmt.Printf("wrote %d bytes\n", n2)
}
wasmup
  • 14,541
  • 6
  • 42
  • 58
  • Thanks for answer. but i dont want to wait in main() for func F to complete. I want Func F to be running background without main() – akshay Sep 06 '19 at 08:52
  • Should you need to exit main, then you must use `os.exec` or [syscall](https://golang.org/pkg/syscall/) and in Go the goroutines are the way to go for concurrency, no other way around. and when you exit the `main()` all goroutines terminated with main. – wasmup Sep 06 '19 at 09:08
1

You can use go channel to wait until child process completes its execution.


func f(ch chan bool) {

    d1 := []byte("hello\ngo\n")
    err := ioutil.WriteFile("test", d1, 0644)
    if err != nil {
        fmt.Println(err.Error())
    }

    file, err := os.Create("test")
    if err != nil {
        fmt.Println(err.Error())
    }

    defer file.Close()

    d2 := []byte{115, 111, 109, 101, 10}
    n2, err := file.Write(d2)
    if err != nil {
        fmt.Println(err.Error())
    }

    fmt.Printf("wrote %d bytes\n", n2)

    ch <- true

}

func main() {

    ch := make(chan bool)
    go f(ch)

    <-ch
    fmt.Println("done")
}
Kamol Hasan
  • 12,218
  • 1
  • 37
  • 46
  • Sorry i want to exit out my main program and return back control to other program which called this program. But dont want to wait for func F to complete execution but want to run it background. – akshay Sep 06 '19 at 08:48
0

It seems impossible that your function f runs in background with your func main exited.Because the child goroutines will exit when main goroutine(the goroutine who created them) exits.

SpiderShrimp
  • 146
  • 1
  • 8