I tried to insert Item by using goroutines ( 2000 goroutines)
so run below code
package main
import (
"fmt"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
"log"
"sync"
)
type Item struct {
Id int `db:"id"`
Title string `db:"title"`
Description string `db:"description"`
}
// ConnectPostgresDB -> connect postgres db
func ConnectPostgresDB() *sqlx.DB {
connstring := "user=postgres dbname=postgres sslmode=disable password=postgres host=localhost port=8080"
db, err := sqlx.Open("postgres", connstring)
if err != nil {
fmt.Println(err)
return db
}
return db
}
func InsertItem(item Item, wg *sync.WaitGroup) {
defer wg.Done()
db := ConnectPostgresDB()
defer db.Close()
tx, err := db.Beginx()
if err != nil {
fmt.Println(err)
return
}
_, err = tx.Queryx("INSERT INTO items(id, title, description) VALUES($1, $2, $3)", item.Id, item.Title, item.Description)
if err != nil {
fmt.Println(err)
}
err = tx.Commit()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Data is Successfully inserted!!")
}
func main() {
var wg sync.WaitGroup
//db, err := sqlx.Connect("postgres", "user=postgres dbname=postgres sslmode=disable password=postgres host=localhost port=8080")
for i := 1; i <= 2000; i++ {
item := Item{Id: i, Title: "TestBook", Description: "TestDescription"}
//go GetItem(db, i, &wg)
wg.Add(1)
go InsertItem(item, &wg)
}
wg.Wait()
fmt.Println("All DB Connection is Completed")
}
after run above code , I think 2000'th rows in items table
But in items table , there are only 150'rows exists
too many clients Error in db server so i increased max_connections 100 -> 4000
and then tried again
But Results is same
Does anybody know why these results occurs???
The problem is that you do not really seem to note the cause of the error.
With a slightly adjusted
main.go, the problem should become rather obvious:And indeed the application logs an error in my test setup:
So, we need to add a control for that:
And sure enough, the result is as expected:
Quite some hassle for something so (deceivingly) simple, right?
Now here comes the REALLY troubling part:
If we have a look at the simplified version (full code in the aptly named "simplified" branch):
Not only is
mainmuch more readable and a lot less complicated - it is of comparable speed. Actually, in my totally non-scientific tests all runs were on average 100ms faster than with the goroutine hassle.Summary
To make a very long story short: Conventional wisdom has it that premature optimization is the root of all evil. And concurrency is not parallelism.
Do not use goroutines unless you have to, check your errors and react to them.