Domain object and repository
The next step is to define the domain object and the repository. In the website
package, create two new files: website.go
and repository.go
, and copy their contents that you can see on this page into them.
A Website
is a struct that contains simple data about the website - its name, URL, position in the ranking, and numeric identifier. Objects of this type will be stored and retrieved from the database.
The Repository
is our interface for reading and writing Website
data from and to the database. Note that the methods of this interface do not depend on PostgreSQL at all. This is one of the main goals of the Repository
pattern - hiding database implementation details and providing a simple API to interact with any database.
After the changes, the project structure should look like this:
postgresql-intro
├── app
├── cmd
├── go.mod
└── website
├── repository.go
└── website.go
We will go through what each method does in the next step, but by now, you may be wondering why every method signature has ctx context.Context
in the parameter list.
In short, the context.Context
is an object that is a common Go concept used by web applications to send request-scoped values, cancellation, and deadline signals to deeper layers of services. Let’s assume that in your application you want to wait a maximum of 5 seconds for a response from the database to prevent the application to wait idly if there are any connection problems. To ensure this, you can create a new Context
with a defined timeout of 5 seconds. The functions of a client or driver operating directly on the database, while receiving such a Context
, respect it, which means that after the timeout of 5 seconds is exceeded, the connection is interrupted, and the application can continue to run.
In our demo application, we will also use this feature and set a timeout for all operations using the context.Context
.
website/website.go
package website
type Website struct {
ID int64
Name string
URL string
Rank int64
}
website/repository.go
package website
import "context"
type Repository interface {
Migrate(ctx context.Context) error
Create(ctx context.Context, website Website) (*Website, error)
All(ctx context.Context) ([]Website, error)
GetByName(ctx context.Context, name string) (*Website, error)
Update(ctx context.Context, id int64, updated Website) (*Website, error)
Delete(ctx context.Context, id int64) error
}