Trying to implement singleton while using database


(cinematik) #1

I’m trying to implement singleton while using database.

main.go

	db := dbcon.Singleton()
	err := db.Ping() // panic here
	if err != nil {
		panic(err)
	}
	fmt.Println("Successfully connected!")

in package dbcon I implement singleton this way:

var db *sql.DB // singleton
var once sync.Once

func Singleton() *sql.DB {
	once.Do(func() {
		psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
			host, port, user, password, dbname)
		db, err := sql.Open("postgres", psqlInfo)
		if err != nil {
			panic(err)
		}
		defer db.Close()
	})
	return db
}

But I got in main.go

panic: runtime error: invalid memory address or nil pointer dereference

What is wrong with this implementation?


(George Calianu) #2

Is because of defer db.Close(). You try to use the database after you closed it.
:face_with_hand_over_mouth:


(cinematik) #3

If I comment deffer nothing changed. But I’m able successfully ping from inside Singleton(), but in main it is still paniking.


(cinematik) #4

As I found out it was beccause I’ve not initialize var db which is outside of the Singleton() and after I changed name inside and then reassigned it to db it works but I’m not sure is it good solution.


(Ignacio Gómez) #5

You were redeclaring db inside the function called at once.Do, shadowing the global db variable and thus effectively returning and uninitialized pointer.