# Using creator to work with structs initialization
## Problem
Let's assume we have a struct and it has many fields, and we want to initialize it. One way to do it is to initialize with all fields but this is messy and also all the fields need to be public or we will need setters.
For Example :
```go=
type EnqueueRequest struct {
Client *asynq.Client
Task *asynq.Task
IsLockRequired bool
MaxRetries int
}
func initialize() {
req := &EnqueueRequest{
Client:something,
Task:something,
IsLock....
Max.....
}
}
```
This is an example of a struct with 4 fields, what if there are more fields? Working with this approach will make things messy as well as annoying for developer.
## Solution
- First we will make all fields of the struct private
```go=
type EnqueueRequest struct {
client *asynq.Client
task *asynq.Task
isLockRequired bool
maxRetries int
}
```
- Now we will create a private struct (creator) and define methods based on all the possibilities a developer might need or ways to create the original struct
```go=
type newEnqueueRequestCreator struct{}
func (it *newEnqueueRequestCreator) DefaultLock(
maxTry int,
client *asynq.Client,
task *asynq.Task,
) *EnqueueRequest {
return &EnqueueRequest{
client: client,
task: task,
maxRetries: maxTry,
isLockRequired: true,
}
}
func (it *newEnqueueRequestCreator) Default(
maxTry int,
client *asynq.Client,
task *asynq.Task,
) *EnqueueRequest {
return &EnqueueRequest{
client: client,
task: task,
maxRetries: maxTry,
}
}
func (it *newEnqueueRequestCreator) DefaultMaxTryLock(
client *asynq.Client,
task *asynq.Task,
) *EnqueueRequest {
return &EnqueueRequest{
client: client,
task: task,
maxRetries: maxTries,
isLockRequired: true,
}
}
......
```
- Now we will create a var through which outside packages can access this creator
```go=
var (
NewEnqueueRequest = &newEnqueueRequestCreator{}
)
```
- Now when calling we will call based on what we need, so lets say the developer needs the locked version with default max tries
```go=
enqueueRequest := somepackage.NewEnqueueRequest.DefaultMaxTryLock(client,task)
```
- Now we can extend with other creators, so if a package has multiple creator we can wrap them up in a single creator and expose it.
```go=
type newCreator struct {
EnqueueRequest newEnqueueRequestCreator
Others....
}
// then expose var
var (
New = &newCreator{}
)
// call from outside
req := somepackage.
New.
Enqueue.
DefaultMaxTryLock(
...params)
```
<!-- ## Question
- Why didn't we use functions directly to get the struct ?
```go=
type EnqueueRequest struct {
client *asynq.Client
task *asynq.Task
isLockRequired bool
maxRetries int
}
func DefaultLock(
maxTry int,
client *asynq.Client,
task *asynq.Task,
) *EnqueueRequest {
return &EnqueueRequest{
client: client,
task: task,
maxRetries: maxTry,
isLockRequired: true,
}
}
``` -->