I have a scenario where I have a few structs to model my database schema. What I want is to add a few methods to all those structs, so that I can use them in my handler. I achieved this using composition, but I have log utils in my parent struct, which is not getting initialized in child structs, because of which I am getting the following error
panic: runtime error: invalid memory address or nil pointer dereference
Suppose my parent struct is something like following
//Model is the top level model instance
type Model struct {
utils *utils.Util
}
// New creates an instance of model
func New(utils *utils.Util) *Model {
return &Model{utils: utils}
}
// Initialize creates/opens database
func (m *Model) Initialize() bool {
db, err := m.openConnection()
if err != nil {
return false
}
defer db.Close()
ctx, cancelfunc := context.WithTimeout(context.Background(), 5*time.Second)
defer cancelfunc()
err = db.PingContext(ctx)
if err != nil {
m.utils.Log.Errorf("FAILED::could not ping database because of %s", err.Error())
return false
}
return true
}
My Child Struct looks something like following
// User act as model for database
type User struct {
*Model
FirstName string `sql:"firstName"`
}
And in my handler method, I have the following
user := new(model.User)
err := user.Initialize()
Everything works fine as expected, but throws an error only when PingContext returns an error. The error that I get is following
panic: runtime error: invalid memory address or nil pointer dereference
This works fine when I call this method directly from the parent struct. Is there any better way to achieve what I want to achieve or am I doing something wrong. Please suggest.
I know in case when the method is called from child struct it is complaining that m.utils is not initialized because of which I am getting an error, but incase of parent struct it is initialized and I am not getting error.
You embedded a *Model
in the user struct, which is initially nil. When you call user.Initialize
, the initialize method is called with a nil receiver. You either have to initialize that model to point to a non-nil struct, or embed non-pointer. Since you also have to initialize the Model
, you can do this:
type User struct {
*Model
FirstName string `sql:"firstName"`
}
You have to initialize the Model and the utils in that model:
u:=new(model.User)
u.Model=model.New(utils)
u.Initilize()