Bug in Concurrent Go program

Hello :raised_hand:
I want the two functions api and handle to work concurrently, But the program doesn’t run properly, How can I fix it? I should also say that I can’t move the api function into the loop of the handle function (Because in the main project the handle function is a part of the net/http std library)

package main

func api() {
        println("api")
}

func handle() {
        for {
                println("handle")
        }
}

func main() {
        for {
                go api()
                go handle()
        }
}

Tell me if my work is completely wrong!

What are you trying to do?

As the program is written now, api will print "api" and then return, so even though you’re constantly spawning api goroutines, they do eventually terminate. handle, on the other hand, runs an infinite loop itself, so every iteration through the for loop in main results in a new goroutine printing "handle" that will never return, so this program will eat all of your memory very quickly.

I know it fills up memory fast, but the main program has to do it forever!

In fact, this project has become very strange. In general, I want to do the following:
First, the Endpoints and its Services must be available
Second, work with an API while the Services is available

That’s why it came to my mind the Concurrent, but it became very difficult.

We need more information about what you’re trying to do to give you better feedback. What you have right now cannot work and doesn’t seem to have any useful purpose: You can’t start goroutines in an endless for loop without any synchronization. It’s the same thing as doing something like this:

package main

func main() {
    var vs []int
    for {
        vs = append(vs, 0)
    }
}

It will allocate as much memory as possible and then panic. Having your main function starting goroutines in an endless for loop is the same thing; there’s nothing useful that can come of it.

Can we get more information on the API? When I think of an API, I think of a service that waits for requests to come in and then as they come in, they’re handled. The way you’re using this api looks more like a worker process to me: It starts, performs some work (i.e. println("api")) and then returns, however, with worker processes, there’s usually some synchronization to limit the number of goroutines or else they’ll eat up all the resources on your computer.

We definitely need more info on the purpose of the handle function. You can’t have an endless loop of starting goroutines when those goroutines are themselves in endless loops that never stop; it’s the same as appending to a slice like I had above: The only outcome is you run out of memory.

I guess I’d think of the problem as something more like:

package main

func api() {
        println("api")
        http.ListenAndServe(http.HandlerFunc(handle))
}

func handle(w http.ResponseWriter, r *http.Request) {
        println("handle")
}

func main() {
        // TODO: Put this into a goroutine when there are more background
        // tasks to start from main. We're keeping it as a normal function call
        // so that main doesn't return.
        api()
}

I think the main project code can better convey what I mean.

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"

	"github.com/mtarif98/go-gateio/database"
	"github.com/mtarif98/go-gateio/json"
)

func getJson() []byte {
	resp, err := http.Get("https://data.gateapi.io/api2/1/tickers")
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	bytes, _ := ioutil.ReadAll(resp.Body)
	return bytes
}

func handleCreate(w http.ResponseWriter, req *http.Request) {
	data := gjson.DecodeJson(req)
	fmt.Println(data)
}

func workWithApi() {
	data := getJson()

	var config database.DBData
	database.LoadDBData(&config)
	targetDB := fmt.Sprintf(
		"%s:%s@tcp(%s:%s)/%s",
		config.DBUsername,
		config.DBPassword,
		config.DBAddress,
		config.DBPort,
		config.DBName,
	)

	cryptosFiltered := gjson.GetEssentialInformation(data)
	database.CreateRecords(cryptosFiltered, targetDB) // for now CreateRecords function write a simple log - TEMPORARY
}

func handleRequests() {
	http.HandleFunc("/api/v1/user/create/", handleCreate)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

func main() { // here i want handleRequests() and workWithApi work concurrently, I mean, while the program is running on the web, it is also working with the API.
	handleRequests() // handle
	workWithApi() // api
}

I understand what you mean.

I think you would benefit from changing main to:

func main() {
    go workWithApi()
    handleRequests()
}

This starts workWithApi in its own goroutine and then lets the main goroutine run http.ListenAndServe

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.