Last active
March 2, 2024 00:49
-
-
Save dezren39/d98e83ee763011cbf62313b95678b230 to your computer and use it in GitHub Desktop.
This file contains 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
// https://github.com/samber/do/issues/30#issuecomment-1705616069 | |
// https://play.golang.org/p/yHLzoV9To_5 | |
package main | |
import ( | |
"errors" | |
"fmt" | |
"sync" | |
) | |
type key[T any] struct{ name string } | |
type provider[T any] func() (T, error) | |
var services = make(map[any]any) | |
var servicesMutex sync.RWMutex | |
func ProvideNamed[T any](name string, p provider[T]) { | |
servicesMutex.Lock() | |
defer servicesMutex.Unlock() | |
services[key[T]{name}] = p | |
} | |
func ProvideNamedValue[T any](name string, v T) { | |
servicesMutex.Lock() | |
defer servicesMutex.Unlock() | |
services[key[T]{name}] = v | |
} | |
func InvokeNamed[T any](name string) (T, error) { | |
servicesMutex.RLock() | |
defer servicesMutex.RUnlock() | |
if provider, ok := services[key[T]{name}].(provider[T]); ok { | |
return provider() | |
} | |
if value, ok := services[key[T]{name}].(T); ok { | |
return value, nil | |
} | |
return empty[T](), errors.New("not found") | |
} | |
func Provide[T any](p provider[T]) { | |
ProvideNamed[T]("", p) | |
} | |
func ProvideValue[T any](v T) { | |
ProvideNamedValue[T]("", v) | |
} | |
func Invoke[T any]() (T, error) { | |
return InvokeNamed[T]("") | |
} | |
func empty[T any]() (t T) { | |
return | |
} | |
func main() { | |
Provide(func() (int, error) { | |
return 42, nil | |
}) | |
ProvideValue("Hello, world!") | |
if val, err := Invoke[int](); err == nil { | |
fmt.Println("Invoke[int]():", val) | |
} else { | |
fmt.Println("Invoke[int]():", err) | |
} | |
if val, err := Invoke[string](); err == nil { | |
fmt.Println("Invoke[string]():", val) | |
} else { | |
fmt.Println("Invoke[string]():", err) | |
} | |
type person struct { | |
name string | |
} | |
Provide(func() (person, error) { | |
return person{"Drew"}, nil | |
}) | |
ProvideNamedValue("customPerson", person{"Drewry"}) | |
if val, err := Invoke[person](); err == nil { | |
fmt.Println("Invoke[person]():", val.name) | |
} else { | |
fmt.Println("Invoke[person]():", err) | |
} | |
if val, err := InvokeNamed[person]("customPerson"); err == nil { | |
fmt.Println("InvokeNamed[person](\"customPerson\"):", val.name) | |
} else { | |
fmt.Println("InvokeNamed[person](\"customPerson\"):", err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment