Skip to content

Instantly share code, notes, and snippets.

@arunsrin
Created June 13, 2021 07:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arunsrin/030f0818a6ead6c55243c15f190fa682 to your computer and use it in GitHub Desktop.
Save arunsrin/030f0818a6ead6c55243c15f190fa682 to your computer and use it in GitHub Desktop.
from the book "Learning Go"
package main
import (
"errors"
"fmt"
"net/http"
)
func main() {
l := LoggerAdaptor(LogOutput)
ds := NewSimpleDataStore()
logic := NewSimpleLogic(l, ds)
c := NewController(l, logic)
http.HandleFunc("/hello", c.SayHello)
http.ListenAndServe(":8080", nil)
}
func LogOutput(message string) {
fmt.Println(message)
}
type SimpleDataStore struct {
userData map[string]string
}
func (sds SimpleDataStore) UserNameForID(userID string) (string, bool) {
name, ok := sds.userData[userID]
return name, ok
}
func NewSimpleDataStore() SimpleDataStore {
return SimpleDataStore{
userData: map[string]string{
"1": "Fred",
"2": "Mary",
"3": "Pat",
},
}
}
// We define interfaces for our actual business logic, since
// we may move our logger and simpledatastore to something
// more complex later..
type DataStore interface {
UserNameForID(userID string) (string, bool)
}
type Logger interface {
Log(message string)
}
// Logoutput needs to adhere to this interface now..
type LoggerAdaptor func(message string)
func (lg LoggerAdaptor) Log(message string) {
lg(message)
}
type SimpleLogic struct {
l Logger
ds DataStore
}
func (sl SimpleLogic) SayHello(userID string) (string, error) {
sl.l.Log("in SayHello for " + userID)
name, ok := sl.ds.UserNameForID(userID)
if !ok {
return "", errors.New("unknown user")
}
return "Hello, " + name, nil
}
func (sl SimpleLogic) SayGoodbye(userID string) (string, error) {
sl.l.Log("in SayGoodbye for " + userID)
name, ok := sl.ds.UserNameForID(userID)
if !ok {
return "", errors.New("unknown user")
}
return "Goodbye, " + name, nil
}
func NewSimpleLogic(l Logger, ds DataStore) SimpleLogic {
return SimpleLogic{
l: l,
ds: ds,
}
}
// Now the API
type Logic interface {
SayHello(userID string) (string, error)
}
type Controller struct {
l Logger
logic Logic
}
func (c Controller) SayHello(w http.ResponseWriter, r *http.Request) {
c.l.Log("In Say Hello")
userID := r.URL.Query().Get("user_id")
message, err := c.logic.SayHello(userID)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
w.Write([]byte(message))
}
// factory function for this too.. accept interface, return
// structs
func NewController(l Logger, logic Logic) Controller {
return Controller{
l: l,
logic: logic,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment