如何在新进程中执行方法

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.