Create your first model

In this tutorial you will learn how to create a model which consist of properties that can be stored in a database. It is sometimes referred to as an entity or a repository. Regardless of naming convention, it is essentially a table in a database.

A model can have relationships to other models. It can and should contain all business logic. Let's get started and create our first model.

Create a new model

In our phonebook project, we will need a way to store and retrieve contacts. Potentially search through them, and even sort them. To do this, we will create a new model called Contact. It's as simple as creating a new file named contact.go in the models directory. Within that file, we will define the Contact struct and it's properties as if we're describingh a new table in a database.

Contact

file: pkg/db/models/contact.go
package models

type Contact struct {

    ModelBase
    
    FirstName string `gorm:"size:255"`
    LastName  string `gorm:"size:255"`
    Nickname  string `gorm:"size:255"`
    Email     string `gorm:"size:255"`
    Phone     string `gorm:"size:255"`
    
}

Let's go throught the above code and unpack what we have done.

  1. We have defined a new struct called Contact.
    This corresponds to a table in our database named contacts (automatic plural of contact).
  2. We have added the ModelBase struct to the Contact struct.
    This is a helper struct that contains the fields ID, CreatedAt and UpdatedAt properties.
  1. We have added the FirstName, LastName, Email and Phone fields to the Contact struct.
    These fields correspond to the columns in our database table.
    The type of each field is string which means a VARCHAR column in our database.

Now that we've defined the Contact struct, we've locked in how our application will view that table in the database. If that table changes somehow, it won't affect our application for as long as those columns exist.

Next up, we need to create a way to interact with that table.


Saving a new contact

We need a save method to save a new contact to the database. Here's how that looks like:

It's very straight forward. We use the db object to create a new record.
The db object holds the database connection. We pass in the model to the db.Model function that helps gorm identify the table.
Then we pass in the &model itself to the Create function that creates the new record.

Next we'll look at how we can retrieve our contacts.

Contact

file: pkg/db/models/contact.go
...
func (model *Contact) Save() error {
    return db.Model(model).Create(&model).Error
}

Retrieving contacts

To retrieve our contacts, we need to create a method that queries the database. Here's how that looks like:

The FindAll method is expected to return two named values.
The first is a slice of contacts named ms.
The second is an error named err.

We use the db object which holds the connection to the database.
We pass in the model to the db.Model function that helps gorm identify the table.
Then we pass in the &ms variable to the Find function that retrieves all records within our database table and assigns them to the ms variable.

Contact

file: pkg/db/models/contact.go
...
func (model *Contact) FindAll() (ms []*Contact, err error) {
    result := db.Model(model).Find(&ms)
    return ms, result.Error
}

Model accessibility

You're most likely to access your models from your API handlers or controllers. Hence, it's a good idea to create an easy way to gain access our Contact struct methods very quickly with little code.

To do this, you can create a new function that returns a pointer to your model. What it returns is a pointer to an empty Contact struct.

Placing this function at the very top of the file (before the Contact struct definition) is a good idea because:

  1. It's unlikely to ever change.
  2. It's easy to access when you need to remember the model name.
  3. It's good to maintain a standard throughout your application code.

Contact

file: pkg/db/models/contact.go
var contact *Contact = &Contact{}

func ContactModel() *Contact {
    return contact
}
...

Complete code

Contact

file: pkg/db/models/contact.go
package models

var contact *Contact = &Contact{}

func ContactModel() *Contact {
    return contact
}

type Contact struct {
    ModelBase
    FirstName string `gorm:"size:255"`
    LastName  string `gorm:"size:255"`
    Nickname  string `gorm:"size:255"`
    Email     string `gorm:"size:255"`
    Phone     string `gorm:"size:255"`
}

func (model *Contact) Save() error {
    return db.Model(model).Create(&model).Error
}

func (model *Contact) FindAll() (ms []*Contact, err error) {
    result := db.Model(model).Find(&ms)
    return ms, result.Error
}

Was this page helpful?

Consider supporting my work if you find it useful

Buy me a coffee