Last active
December 14, 2016 14:16
-
-
Save drgomesp/b2f0428fe58c03bfc1d2c47a97dec8d8 to your computer and use it in GitHub Desktop.
Lazy object initialization in Go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"log" | |
"math/rand" | |
"time" | |
) | |
type A struct{} | |
type B struct{} | |
func (a *A) bar() {} | |
func (b *B) bar() {} | |
// ServiceInterface that will be implemented by both the concrete service and the service proxy | |
type ServiceInterface interface { | |
foo() | |
} | |
// Service with some dependencies | |
type Service struct { | |
a *A | |
b *B | |
} | |
func (s *Service) foo() { | |
s.a.bar() | |
s.b.bar() | |
log.Printf("Service::foo()") | |
} | |
// ServiceProxy for lazy initialization of Service | |
type ServiceProxy struct { | |
*Service | |
initialized bool | |
initializer func(a *A, b *B) *Service | |
} | |
// NewServiceProxy initializer function (should be blazing fast) | |
func NewServiceProxy(initializer func(a *A, b *B) *Service) *ServiceProxy { | |
start := time.Now() | |
elapsed := time.Since(start) | |
log.Printf("NewServiceProxy() took %s", elapsed) | |
return &ServiceProxy{ | |
initializer: initializer, | |
} | |
} | |
func (p *ServiceProxy) foo() { | |
if p.initialized == false { | |
p.initialized = true | |
// Container will be responsible for initializing the dependencies | |
a := &A{} | |
b := &B{} | |
p.Service = p.initializer(a, b) | |
} | |
p.Service.foo() | |
} | |
// NewService initializer function | |
func NewService(a *A, b *B) *Service { | |
// Some random sleep to simulate heavy initialization | |
start := time.Now() | |
time.Sleep(time.Duration(rand.Intn(1500)) * time.Millisecond) | |
elapsed := time.Since(start) | |
log.Printf("NewService() took %s", elapsed) | |
return &Service{ | |
a: a, | |
b: b, | |
} | |
} | |
// Some function that takes a service interface pointer | |
func bar(service ServiceInterface) { | |
service.foo() | |
} | |
func main() { | |
a := &A{} | |
b := &B{} | |
service := NewService(a, b) | |
proxy := NewServiceProxy(NewService) | |
bar(service) | |
bar(proxy) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output: