Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recursive function in go language

Tags:

go

I started to learn go language days ago. When I tried to start writing some fun codes, I am stuck by a strange behavior.

package main

import "fmt"

func recv(value int) {
    if value < 0 {
        return
    }

    fmt.Println(value)
    go recv(value-1)
}

func main() {
    recv(10)
}

when I run the above code, only 10 is printed. When I remove the go before the call to recv, 10 to 0 are printed out. I believe I am misusing go routine here, but I can not understand why it failed start a go routine this way.

like image 893
ethangao Avatar asked Nov 12 '12 04:11

ethangao


People also ask

Does Golang support recursion?

The Go programming language supports recursion. That is, it allows a function to call itself. But while using recursion, programmers need to be careful to define an exit condition from the function, otherwise it will go on to become an infinite loop.

What are the criteria for recursion in go?

Go accepts recursion functions. A function is recursive if it calls itself and reaches a stop condition. In the following example, testcount() is a function that calls itself. We use the x variable as the data, which increments with 1 ( x + 1 ) every time we recurse.

What is recursive function in JS?

Recursion is a process of calling itself. A function that calls itself is called a recursive function. The syntax for recursive function is: function recurse() { // function code recurse(); // function code } recurse(); Here, the recurse() function is a recursive function.


2 Answers

When the main function returns, Go will not wait for any still existing goroutines to finish but instead just exit.

recv will return to main after the first "iteration" and because main has nothing more to do, the program will terminate.

One solution to this problem is to have a channel that signals that all work is done, like the following:

package main

import "fmt"

func recv(value int, ch chan bool) {
    if value < 0 {
        ch <- true
        return
    }

    fmt.Println(value)
    go recv(value - 1, ch)
}

func main() {
    ch := make(chan bool)
    recv(10, ch)

    <-ch
}

Here, recv will send a single boolean before returning, and main will wait for that message on the channel.

For the logic of the program, it does not matter what type or specific value you use. bool and true are just a straightforward example. If you want to be more efficient, using a chan struct{} instead of a chan bool will save you an additional byte, since empty structs do not use any memory.

like image 198
Dominik Honnef Avatar answered Oct 29 '22 11:10

Dominik Honnef


A sync.Waitgroup is another solution and specifically intended for the purpose of waiting for an arbitrary amount of goroutines to run their course.

package main

import (
    "fmt"
    "sync"
)

func recv(value int, wg *sync.WaitGroup) {
    if value < 0 {
        return
    }

    fmt.Println(value)

    wg.Add(1) // Add 1 goroutine to the waitgroup.

    go func() {
        recv(value-1, wg)
        wg.Done() // This goroutine is finished.
    }()
}

func main() {
    var wg sync.WaitGroup
    recv(10, &wg)

    // Block until the waitgroup signals
    // all goroutines to be finished.
    wg.Wait()
}
like image 34
jimt Avatar answered Oct 29 '22 10:10

jimt