It's a bit hard to write a title that match with my current problem.. I have a main() function which uses a function in another package (database_sql). This function initializes a global variable sql.DB*. After the initialization, the variable isn't nil, but for the others functions, this variable is still nil.. Let see the code below !
main.go
package main
import (
"net/http"
db "./database_sql"
router "./router"
)
func main() {
db.Init_SQL();
router.Init_routes()
http.ListenAndServe(":8080", router.GetRouter())
}
db.go
package database_sql
import (
"fmt"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
var DB *sql.DB // global variable to share it between main and the HTTP handler
//var dbi *databaseinfos
func Init_SQL() {
dbi := databaseinfos{
user: "something",
password: "something",
name: "something",
address: "something",
port: "2323",
url: ""}
dbi.url = (dbi.user + ":" + dbi.password + "@tcp(" + dbi.address + ":" + dbi.port + ")/" + dbi.name)
db_init_var, err := sql.Open("mysql", dbi.url)
if err != nil {
fmt.Println("Error on initializing database connection: %s", err.Error())
}
err = db_init_var.Ping()
if err != nil {
fmt.Println("Error on opening database connection: %s", err.Error())
}
// Here, as you can test, my variable is initialized
if err == nil {
DB = db_init_var
if DB == nil {
fmt.Println("NIL DB !!")
}
if db_init_var == nil {
fmt.Println("NIL db_init_var !!")
}
fmt.Println(dbi.url)
}
}
Now, everything is ok ! I will now test http://xxxxxxx/login with an username/password. Everything's working fine and now, it's the time to make a request in the database with my DB variable declared above.
request_user.go
package database_sql
import (
"encoding/json"
"fmt"
"net/http"
m "models"
)
func CanLogin(user m.User) (bool, m.User, m.StatusBack) {
// Prepare statement for reading data
stmtOut, err := DB.Prepare("SELECT username, password, token FROM users WHERE username = ? AND password = ?")
if err != nil {
return false, user, m.StatusBack{ToString: err.Error(), IdStatus: http.StatusInternalServerError}
}
defer stmtOut.Close()
// Query the user
err = stmtOut.QueryRow(user.Username, user.Password).Scan(&user.Username, &user.Password, &user.UUID) // WHERE user is registered
if err != nil {
return false, user, m.StatusBack{ToString: "User not found.", IdStatus: http.StatusNotFound}
} else {
j, err := json.Marshal(user)
if err == nil {
return true, user, m.StatusBack{ToString: string(j), IdStatus: http.StatusOK}
} else {
return false, user, m.StatusBack{ToString: err.Error(), IdStatus: http.StatusInternalServerError}
}
}
}
However, when I'm making my sql request, the following line says that DB is nil. stmtOut, err := DB.Prepare("SELECT username, password, token FROM users WHERE username = ? AND password = ?")
I made lot of test such as trying to initialize it with '=' and no ':='. I tried 'if DB == nil' statement and DB is always nil.. Why? I initialize my database var before initialize my router, so technically, when my router give a redirection to a function, this function wouldn't use a database var (DB) nil, isn't?
Thank for your answers !
EDIT 2 I red your answers and then, I edited my code like you asked with some adds. After init_SQL, DB isn't nil !
main.go
package main
import (
"fmt"
"net/http"
db "./database_sql"
router "./router"
)
func main() {
if db.Init_SQL() == true {
if db.DB == nil {
fmt.Println("db.DB is nil !")
}
if router.Init_routes() == true {
http.ListenAndServe(":8080", router.GetRouter())
}
}
}
So, now my 2 init functions return true on success and false on failure. I thought it could be an asynchronous problem, I made it like that to wait the end of each functions to continue my 'step by step'
db.Init_SQL();
? – MelvinDB
value afterdb.Init_SQL()
and afterrouter.Init_routes()
, also before/after every function call you made in your calling stack, in this way you might have an idea when yourDB
get reset, or haven't been set at all. – nevets