0

I am working on a go restapi with fiber, but I hit a snag with an error I am not sure how to debug. The error seems to be coming from the prepare statement I am using to insert data into the database.

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x90b6f3]

goroutine 66 [running]:
database/sql.(*DB).conn(0x0, {0xb0e920, 0xc0001c6048}, 0x1)
    /usr/local/go/src/database/sql/sql.go:1290 +0x53
database/sql.(*DB).prepare(0xc00013e680?, {0xb0e920, 0xc0001c6048}, {0xa4ae4a, 0x9d}, 0x75?)
    /usr/local/go/src/database/sql/sql.go:1588 +0x45
database/sql.(*DB).PrepareContext(0xb0b360?, {0xb0e920, 0xc0001c6048}, {0xa4ae4a, 0x9d})
    /usr/local/go/src/database/sql/sql.go:1557 +0x98
database/sql.(*DB).Prepare(...)
    /usr/local/go/src/database/sql/sql.go:1578
github.com/davidshare/property-website-backend/repository/postgres.(*User).CreateUser(0xc0000b2000)
    /home/davidshare/go/src/github.com/davidshare/property-website-backend/repository/postgres/user.go:27 +0xbd
github.com/davidshare/property-website-backend/service.CreateUser(0xc0000b2000)
    /home/davidshare/go/src/github.com/davidshare/property-website-backend/service/user.go:15 +0xa7
github.com/davidshare/property-website-backend/controllers.CreateUser(0xc0001d9080)
    /home/davidshare/go/src/github.com/davidshare/property-website-backend/controllers/user.go:37 +0x351
github.com/gofiber/fiber/v2.(*App).next(0xc0017da5a0, 0xc0001d9080)
    /home/davidshare/go/pkg/mod/github.com/gofiber/fiber/v2@v2.34.1/router.go:132 +0x1be
github.com/gofiber/fiber/v2.(*Ctx).Next(0x40ef45?)
    /home/davidshare/go/pkg/mod/github.com/gofiber/fiber/v2@v2.34.1/ctx.go:802 +0x53
github.com/gofiber/fiber/v2/middleware/logger.New.func2(0xc0001d9080)
    /home/davidshare/go/pkg/mod/github.com/gofiber/fiber/v2@v2.34.1/middleware/logger/logger.go:160 +0x1f4
github.com/gofiber/fiber/v2.(*App).next(0xc0017da5a0, 0xc0001d9080)
    /home/davidshare/go/pkg/mod/github.com/gofiber/fiber/v2@v2.34.1/router.go:132 +0x1be
github.com/gofiber/fiber/v2.(*App).handler(0xc0017da5a0, 0x4d24f7?)
    /home/davidshare/go/pkg/mod/github.com/gofiber/fiber/v2@v2.34.1/router.go:159 +0x45
github.com/valyala/fasthttp.(*Server).serveConn(0xc00185a6c0, {0xb104a0?, 0xc000010028})
    /home/davidshare/go/pkg/mod/github.com/valyala/fasthttp@v1.37.0/server.go:2338 +0x1268
github.com/valyala/fasthttp.(*workerPool).workerFunc(0xc001855e00, 0xc00010e060)
    /home/davidshare/go/pkg/mod/github.com/valyala/fasthttp@v1.37.0/workerpool.go:224 +0xa9
github.com/valyala/fasthttp.(*workerPool).getCh.func1()
    /home/davidshare/go/pkg/mod/github.com/valyala/fasthttp@v1.37.0/workerpool.go:196 +0x38
created by github.com/valyala/fasthttp.(*workerPool).getCh
    /home/davidshare/go/pkg/mod/github.com/valyala/fasthttp@v1.37.0/workerpool.go:195 +0x1b0

This is the code where I create the database connection:

package postgres

import (
    "database/sql"
    "fmt"

    //for connecting to db
    "github.com/davidshare/property-website-backend/config"
    _ "github.com/lib/pq"
)

var (
    DbClient *sql.DB
)

func Init() {
    fmt.Println("we got here")
    config := config.GetConfig()
    connectionString := fmt.Sprintf("host=%s port=%d user=%s "+
        "password=%s dbname=%s sslmode=disable",
        config.DB.Host, config.DB.Port, config.DB.Username, config.DB.Password, config.DB.Name)

    var err error
    DbClient, err = sql.Open("postgres", connectionString)
    if err != nil {
        panic(err)
    }
    defer DbClient.Close()
    fmt.Println((DbClient))
    fmt.Println("Successfully connected to database!")
}

This is where the error is coming from:

func (user *User) CreateUser() (int, error) {
    fmt.Println(user)

    stmt, err := db.DbClient.Prepare("INSERT INTO public.users (firstname,middlename,lastname,phonenumber,email,address,passport,role,password,created_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);")
    print("got here in the repo")
    if err != nil {
        return user.ID, err
    }

    //closing the statement to prevent memory leaks
    defer stmt.Close()
    _, err = stmt.Exec(user.Firstname, user.Middlename, user.Lastname, user.Phonenumber, user.Email, user.Address, user.Passport, user.Role, user.Password, time.Now().Format("2017-09-07 17:06:06 Wednesday"))

    if err != nil {
        return user.ID, err
    }

    return user.ID, nilfunc (user *User) CreateUser() (int, error) {
    fmt.Println(user)

    stmt, err := db.DbClient.Prepare("INSERT INTO public.users (firstname,middlename,lastname,phonenumber,email,address,passport,role,password,created_at) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10);")
    print("got here in the repo")
    if err != nil {
        return user.ID, err
    }

    //closing the statement to prevent memory leaks
    defer stmt.Close()
    _, err = stmt.Exec(user.Firstname, user.Middlename, user.Lastname, user.Phonenumber, user.Email, user.Address, user.Passport, user.Role, user.Password, time.Now().Format("2017-09-07 17:06:06 Wednesday"))

    if err != nil {
        return user.ID, err
    }

    return user.ID, nil
}
}
David Essien
  • 1,463
  • 4
  • 22
  • 36
  • 2
    `defer DbClient.Close()` - why do you close database immediately after you open it? – zerkms Nov 10 '22 at 00:56
  • I just fixed that, thank you. But it doesn't solve the issue. – David Essien Nov 10 '22 at 01:06
  • 1
    Then you have some other bug now: the stacktrace you provided pointed to the closed database. If you don't close it now - then the stracktrace should change. If it has not changed, then you still close it. – zerkms Nov 10 '22 at 01:12
  • No, it has not changed. It is still the same. – David Essien Nov 10 '22 at 01:14
  • 1
    Then it means you either close it somewhere else. Create a simple program that opens the db, and right there runs that query. – zerkms Nov 10 '22 at 01:17
  • I searched the code base, I didn't close it in any other place. However, I noticed something while I was debugging. The issue is with the reference to `db.DbClient`. Once it gets there, it panics and terminates the process. I also tried adding some logs to the init file and found that it doesn't even run any line in the database initialization file. – David Essien Nov 10 '22 at 01:31
  • 2
    Are you expecting the `Init()` function to run automatically or are you calling it from somewhere else? If you are it should be `init()` with lowercase `i` – Pierre Fouilloux Nov 10 '22 at 04:35
  • Thank you very much. I just changed the I in init to lowercase and that resolved it. Thank you. – David Essien Nov 10 '22 at 06:26

0 Answers0