Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding lazy initialisation pattern #122

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ A curated collection of idiomatic design & application patterns for Go language.
| [Factory Method](/creational/factory.md) | Defers instantiation of an object to a specialized function for creating instances | ✔ |
| [Object Pool](/creational/object-pool.md) | Instantiates and maintains a group of objects instances of the same type | ✔ |
| [Singleton](/creational/singleton.md) | Restricts instantiation of a type to one object | ✔ |
| [Lazy Initialisation](/creational/lazy-initialisation.md) | Defer creation of object until actually needed | ✔ |

## Structural Patterns

69 changes: 69 additions & 0 deletions creational/lazy-initialisation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Lazy Initialisation Pattern

While not a traditional design pattern, lazy initialization is a common technique in Go. It involves deferring the creation of an object until it is actually needed. You can use this technique to optimize resource usage.

## Implementation

```go
package main

import (
"fmt"
"sync"
)

// LazyInitializer represents a generic lazy initializer for any type.
type LazyInitializer struct {
mu sync.Mutex
instance interface{}
initialized bool
}

// NewLazyInitializer creates a new LazyInitializer.
func NewLazyInitializer() *LazyInitializer {
return &LazyInitializer{}
}

// GetInstance returns the instance, creating it lazily if necessary.
func (li *LazyInitializer) GetInstance(factory func() interface{}) interface{} {
li.mu.Lock()
defer li.mu.Unlock()

if !li.initialized {
li.instance = factory()
li.initialized = true
}
return li.instance
}
```

## Usage

Given below is an example usage for lazy initialisation.

```go
// Create a LazyInitializer instance.
initializer := NewLazyInitializer()

// Access the resource, which will be created lazily.
resource1 := initializer.GetInstance(func() interface{} {
fmt.Println("Creating a resource...")
return "Resource 1"
})
fmt.Println("Resource 1:", resource1)

// Access the resource again, which should reuse the existing one.
resource2 := initializer.GetInstance(func() interface{} {
fmt.Println("Creating a resource...")
return "Resource 2"
})
fmt.Println("Resource 2:", resource2)

// The resource is created only once, and subsequent accesses reuse it.
```

## Rules of Thumb

- The lazy initialization design pattern is used when you want to defer the creation of an object or resource until it's actually needed, rather than creating it immediately.
- It's important to note that while lazy initialization can be a useful optimization technique, it should be used judiciously.
- In some cases, it might introduce additional complexity or latency if used excessively.