This question already has an answer here:
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
go
")
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
", 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().
</div>
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
go
")
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
", 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
go
")
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
", n2)
}
You can use go channel
to wait until child process completes its execution.
func f(ch chan bool) {
d1 := []byte("hello
go
")
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
", n2)
ch <- true
}
func main() {
ch := make(chan bool)
go f(ch)
<-ch
fmt.Println("done")
}
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.