Skip to content

Instantly share code, notes, and snippets.

@adilsoncarvalho
Created October 12, 2024 10:50
Show Gist options
  • Save adilsoncarvalho/d8c84b9b97d91bf8b2073e70a38332af to your computer and use it in GitHub Desktop.
Save adilsoncarvalho/d8c84b9b97d91bf8b2073e70a38332af to your computer and use it in GitHub Desktop.
Multiple implementations to the same interface in Go
// This code tests how one can create multiple implementations and play with
// them in Go, being an example on how the interface and struct dynamic works.
//
// This code was tested in Go 1.23
//
// # How to run it:
//
// go run main.go
//
// # Output:
// === MemoryStore ===
// SET[MemoryStore] memory0 1000
// GET[MemoryStore] memory0
// === FilesystemStore ===
// SET[FilesystemStore] filesystem3 1000
// GET[FilesystemStore] filesystem3
// === ProxyStore ===
// SET[ProxyStore] proxy1 3000
// SET[MemoryStore] proxy1 3000
// SET[FilesystemStore] proxy1 3000
// GET[ProxyStore] proxy1
// GET[MemoryStore] proxy1
// GET[FilesystemStore] proxy1
//
// Process finished with the exit code 0
package main
import "fmt"
// Store is the interface for the component I want to have multiple
// implementations in my codebase
type Store interface {
// Set stores the value identified by the key.
Set(string, interface{}) bool
// Get retrieves the value identified by the key.
Get(string) interface{}
}
// MemoryStore is the first implementation, storing data in-memory. It has no
// real implementation, as I am keen to see the whole dynamic happening.
type MemoryStore struct {}
// Set stores the value identified by the key. It has no real implementation,
// as I am keen to see the whole dynamic happening.
func (s *MemoryStore) Set(key string, value interface{}) bool {
fmt.Println("SET[MemoryStore]", key, value)
return true
}
// Get retrieves the value identified by the key. It has no real implementation,
// as I am keen to see the whole dynamic happening.
func (s *MemoryStore) Get(key string) interface{} {
fmt.Println("GET[MemoryStore]", key)
return 1
}
// FilesystemStore is the second implementation, storing data in the local
// filesystem. It has no real implementation, as I am keen to see the whole
// dynamic happening.
type FilesystemStore struct {}
// Set stores the value identified by the key. It has no real implementation,
// as I am keen to see the whole dynamic happening.
func (s *FilesystemStore) Set(key string, value interface{}) bool {
fmt.Println("SET[FilesystemStore]", key, value)
return true
}
// Get retrieves the value identified by the key. It has no real implementation,
// as I am keen to see the whole dynamic happening.
func (s *FilesystemStore) Get(key string) interface{} {
fmt.Println("GET[FilesystemStore]", key)
return 1
}
// ProxyStore is the third implementation, and it allows the user to create a
// chain of invocations with all the implementations of Store.
type ProxyStore struct {
Stores []Store
}
// AddStore adds a new store to the proxy store
func (s *ProxyStore) AddStore(store Store) {
s.Stores = append(s.Stores, store)
}
// Set invokes the Set method from all the Store implementation added to Stores
func (s *ProxyStore) Set(key string, value interface{}) bool {
fmt.Println("SET[ProxyStore]", key, value)
for _, store := range s.Stores {
store.Set(key, value)
}
return true
}
// Get invokes the Get method from all the Store implementation added to Stores
func (s *ProxyStore) Get(key string) interface{} {
fmt.Println("GET[ProxyStore]", key)
for _, store := range s.Stores {
store.Get(key)
}
return 1
}
func main() {
var store Store
// create and consume an instance of MemoryStore, assigning it
// to a Store typed variable
fmt.Println("=== MemoryStore ===")
store = &MemoryStore{}
store.Set("memory0", 1000)
store.Get("memory0")
// create and consume an instance of FilesystemStore, assigning it
// to a Store typed variable
fmt.Println("=== FilesystemStore ===")
store = &FilesystemStore{}
store.Set("filesystem3", 1000)
store.Get("filesystem3")
// create and consume an instance of ProxyStore, adding the other store
// implementations before assigning it to a Store typed variable
fmt.Println("=== ProxyStore ===")
proxy := &ProxyStore{}
proxy.AddStore(&MemoryStore{})
proxy.AddStore(&FilesystemStore{})
proxy.Set("proxy1", 3000)
proxy.Get("proxy1")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment