# Repository Pattern (go) - [The Repository pattern: a painless way to simplify your Go service logic](https://threedots.tech/post/repository-pattern-in-go/) ## Interface to abstract actual database layer > [!ai]+ ChatGPT > > The Repository pattern in Go is a design approach that abstracts the data layer, separating the logic of data access from the business logic of the application. It involves creating a repository interface to define operations like fetching, updating, or deleting data, and implementing this interface for specific data storage mechanisms such as relational databases or in-memory storage. Additionally, this pattern can incorporate transaction handling. ```go package hour import ( "context" "time" ) type Repository interface { GetOrCreateHour(ctx context.Context, hourTime time.Time) (*Hour, error) UpdateHour(ctx context.Context, hourTime time.Time, updateFn func(h *Hour) (*Hour, error)) error } ``` ### Implementations 1. **In-Memory Implementation** - **Description**: This implementation uses a Go map to store data in memory. Ideal for scenarios where persistence across service restarts isn't required, like testing or prototyping. - **Transaction Handling**: Simulates transactions using locks (`sync.RWMutex`). The `UpdateHour` method ensures atomic updates to the in-memory data. 2. **MySQL Implementation** - **Description**: Connects to a MySQL database. Well-suited for production-grade applications requiring persistent storage. - **Transaction Handling**: Utilizes SQL transactions. The `UpdateHour` method wraps the `updateFn` in a SQL transaction, committing changes if successful or rolling back in case of errors. 3. **Firestore Implementation** - **Description**: Adapts to Firestore, a NoSQL database, suitable for applications leveraging Google Cloud Platform. - **Transaction Handling**: Leverages Firestore's transaction capabilities. The `UpdateHour` function manages Firestore transactions, ensuring data consistency in distributed environments. ## Usage example ```go package service import ( "context" "hour" "time" ) type HourService struct { repo hour.Repository } func NewHourService(repo hour.Repository) *HourService { return &HourService{repo: repo} } // UpdateHourAvailability updates the availability of an hour. func (s *HourService) UpdateHourAvailability(ctx context.Context, hourTime time.Time, available bool) error { updateFn := func(h *hour.Hour) (*hour.Hour, error) { h.SetAvailability(available) return h, nil } return s.repo.UpdateHour(ctx, hourTime, updateFn) } ``` ## Transaction Handling > [!ai]+ ChatGPT > > In Go's Repository pattern, transaction handling through an update function is typically achieved by defining a method in the repository that wraps business logic within a transaction. This method, often called `Update`, accepts a function as an argument, encompassing the business logic to be executed. Within this method, a transaction is started, the provided function is executed, and depending on the success or failure of this function, the transaction is either committed or rolled back. This design ensures atomic operations and data consistency, encapsulating transaction management within the repository layer.