Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

GoLang – bbolt – invalid memory address or nil pointer dereference

I am trying to use file database bbolt as a key/value storage. Below is my code


package handler

import (
    "encoding/json"
    "log"
    "net/http"
    "os"

    "go.etcd.io/bbolt"
    bolt "go.etcd.io/bbolt"
    yml "gopkg.in/yaml.v3"
)

type urlDB struct {
    db *bbolt.DB
}

func (u urlDB) ensureDB() {
    u.db, _ = bolt.Open("url.db", 0600, nil)
}


func MapHandler(pathsToURLs map[string]string, fallback http.Handler) http.HandlerFunc {

    return func(w http.ResponseWriter, r *http.Request) {
        path := r.URL.Path
        if _, ok := pathsToURLs[path]; ok {
            http.Redirect(w, r, pathsToURLs[path], http.StatusFound)

        } else {
            fallback.ServeHTTP(w, r)
        }
    }

}


func DefaultMap(fallback http.Handler) http.HandlerFunc {
    db := urlDB{}
    db.ensureDB()
    //bkt := db.db.createBucket()
    //createSampleData(bkt)
    defer db.db.Close()

    bktName := "URLBucket"

    createBucket(db.db, bktName)
    addSampleData(db.db, bktName, "/gm", "https://mail.google.com")
    addSampleData(db.db, bktName, "/ym", "https://mail.yahoo.com")
    pathToURLs := make(map[string]string)
    getData(db.db, bktName, pathToURLs)
    return MapHandler(pathToURLs, fallback)
}

func createBucket(db *bbolt.DB, bktName string) {
    db.Update(func(tx *bbolt.Tx) error {
        _, _ = tx.CreateBucketIfNotExists([]byte(bktName))
        return nil
    })
}

func addSampleData(db *bbolt.DB, bktName, key, value string) {
    db.Update(func(tx *bbolt.Tx) error {
        b := tx.Bucket([]byte(bktName))
        _ = b.Put([]byte(key), []byte(value))
        return nil
    })
}

func getData(db *bbolt.DB, bktName string, pathToURLs map[string]string) {
    db.View(func(tx *bbolt.Tx) error {
        b := tx.Bucket([]byte(bktName))
        c := b.Cursor()

        for k, v := c.First(); k != nil; k, v = c.Next() {
            pathToURLs[string(k)] = string(v)
        }
        return nil
    })
}

So while calling this handler:DefaultMap from main.go with below code

mux := http.NewServeMux()
var urlHandler http.HandlerFunc 
urlHandler = handler.DefaultMap(mux)
http.ListenAndServe(":8080", urlHandler)

But I am getting error as below

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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

goroutine 1 [running]:
go.etcd.io/bbolt.(*DB).Close(0x0)
panic({0x686180, 0x8dcb50})
    /usr/local/go/src/runtime/panic.go:1038 +0x215
go.etcd.io/bbolt.(*DB).beginRWTx(0x0)
    /home/xx/coding/go/packages/pkg/mod/go.etcd.io/bbolt@v1.3.6/db.go:634 +0x38
go.etcd.io/bbolt.(*DB).Begin(0x0, 0x0)
    /home/xx/coding/go/packages/pkg/mod/go.etcd.io/bbolt@v1.3.6/db.go:589 +0x1d
go.etcd.io/bbolt.(*DB).Update(0x0, 0xc000187e38)
    /home/xx/coding/go/packages/pkg/mod/go.etcd.io/bbolt@v1.3.6/db.go:725 +0x3e
github.com/xx/urlshortner/handler.createBucket(0x6c588d, {0x6c6358, 0xc000187ec8})
    /home/xx/coding/go/src/urlshortner/handler/handler.go:97 +0x48
github.com/xx/urlshortner/handler.DefaultMap({0x7243e0, 0xc00014a300})
    /home/xx/coding/go/src/urlshortner/handler/handler.go:88 +0x95
main.main()
    /home/xx/coding/go/src/urlshortner/main.go:24 +0xcc
exit status 2

Any help much appreciated.

Thank you.

>Solution :

This line:

github.com/xx/urlshortner/handler.createBucket(0x6c588d, {0x6c6358, 0xc000187ec8})

says error is in createBucket. Looking at createBucket:

    db.Update(func(tx *bbolt.Tx) error {

Based on the stack trace, it calls Update, and db is the only thing that can be nil here.

Tracing the call back, you can see:

func (u urlDB) ensureDB() {
    u.db, _ = bolt.Open("url.db", 0600, nil)
}

Thus, db open failed, and u.db is nil.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading