Copy docker run --rm zchencow/innozverse-go:latest go run - << 'EOF'
package main
import (
"errors"
"fmt"
"sort"
"strings"
)
// Step 4: Custom error types implementing the error interface
type ValidationError struct {
Field string
Message string
}
func (e *ValidationError) Error() string {
return fmt.Sprintf("validation error: %s — %s", e.Field, e.Message)
}
type NotFoundError struct{ ID int; Resource string }
func (e *NotFoundError) Error() string {
return fmt.Sprintf("%s with id=%d not found", e.Resource, e.ID)
}
func findProduct(id int) (string, error) {
products := map[int]string{1: "Surface Pro", 2: "Surface Pen"}
if id <= 0 { return "", &ValidationError{"id", "must be positive"} }
p, ok := products[id]
if !ok { return "", &NotFoundError{id, "product"} }
return p, nil
}
// Step 5: Sorter interface
type Sortable[T any] interface {
Len() int
Less(i, j int) bool
Swap(i, j int)
}
// Step 6: Payment processor
type PaymentMethod interface {
Charge(amount float64) error
Name() string
}
type CreditCard struct{ Last4 string; Balance float64 }
func (c *CreditCard) Charge(amount float64) error {
if amount > c.Balance { return fmt.Errorf("insufficient credit: have %.2f, need %.2f", c.Balance, amount) }
c.Balance -= amount
return nil
}
func (c *CreditCard) Name() string { return "CreditCard *" + c.Last4 }
type PayPal struct{ Email string; Balance float64 }
func (p *PayPal) Charge(amount float64) error {
if amount > p.Balance { return fmt.Errorf("PayPal balance insufficient") }
p.Balance -= amount
return nil
}
func (p *PayPal) Name() string { return "PayPal(" + p.Email + ")" }
type Wallet struct{ Balance float64 }
func (w *Wallet) Charge(amount float64) error {
if amount > w.Balance { return fmt.Errorf("wallet empty") }
w.Balance -= amount
return nil
}
func (w *Wallet) Name() string { return "Wallet" }
func processPayment(method PaymentMethod, amount float64) {
err := method.Charge(amount)
if err != nil {
fmt.Printf(" [%s] FAILED: %s\n", method.Name(), err)
} else {
fmt.Printf(" [%s] Charged $%.2f ✓\n", method.Name(), amount)
}
}
// Step 7: Middleware pattern via interfaces
type Handler interface { Handle(req string) string }
type HandlerFunc func(string) string
func (f HandlerFunc) Handle(req string) string { return f(req) }
func Logger(next Handler) Handler {
return HandlerFunc(func(req string) string {
fmt.Printf("[LOG] request: %s\n", req)
resp := next.Handle(req)
fmt.Printf("[LOG] response: %s\n", resp)
return resp
})
}
func Auth(token string, next Handler) Handler {
return HandlerFunc(func(req string) string {
if !strings.Contains(req, "token="+token) {
return "401 Unauthorized"
}
return next.Handle(req)
})
}
// Step 8: Capstone — plugin registry
type Plugin interface {
Name() string
Execute(input string) (string, error)
}
type UpperPlugin struct{}
func (UpperPlugin) Name() string { return "upper" }
func (UpperPlugin) Execute(s string) (string, error) { return strings.ToUpper(s), nil }
type ReversePlugin struct{}
func (ReversePlugin) Name() string { return "reverse" }
func (ReversePlugin) Execute(s string) (string, error) {
r := []rune(s)
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 { r[i], r[j] = r[j], r[i] }
return string(r), nil
}
type WordCountPlugin struct{}
func (WordCountPlugin) Name() string { return "wordcount" }
func (WordCountPlugin) Execute(s string) (string, error) {
return fmt.Sprintf("words=%d chars=%d", len(strings.Fields(s)), len(s)), nil
}
type PluginRegistry struct{ plugins map[string]Plugin }
func NewRegistry() *PluginRegistry { return &PluginRegistry{plugins: make(map[string]Plugin)} }
func (r *PluginRegistry) Register(p Plugin) { r.plugins[p.Name()] = p }
func (r *PluginRegistry) Run(name, input string) (string, error) {
p, ok := r.plugins[name]
if !ok { return "", fmt.Errorf("plugin %q not found", name) }
return p.Execute(input)
}
func (r *PluginRegistry) List() []string {
names := make([]string, 0, len(r.plugins))
for n := range r.plugins { names = append(names, n) }
sort.Strings(names)
return names
}
func main() {
// Custom errors
for _, id := range []int{1, 99, -1} {
name, err := findProduct(id)
if err != nil {
var notFound *NotFoundError
var valErr *ValidationError
switch {
case errors.As(err, ¬Found): fmt.Printf("Not found: id=%d\n", notFound.ID)
case errors.As(err, &valErr): fmt.Printf("Validation: %s\n", valErr.Message)
default: fmt.Println("Unknown error:", err)
}
} else {
fmt.Println("Found:", name)
}
}
// Payment processing
fmt.Println("\n--- Payments ---")
methods := []PaymentMethod{
&CreditCard{"4242", 500},
&PayPal{"[email protected] ", 200},
&Wallet{50},
}
for _, m := range methods { processPayment(m, 150) }
processPayment(&Wallet{10}, 150)
// Middleware chain
fmt.Println("\n--- Middleware ---")
base := HandlerFunc(func(req string) string { return "200 OK: " + req })
chain := Logger(Auth("secret", base))
chain.Handle("GET /api/products?token=secret")
chain.Handle("GET /api/products")
// Plugin registry
fmt.Println("\n--- Plugins ---")
reg := NewRegistry()
reg.Register(UpperPlugin{})
reg.Register(ReversePlugin{})
reg.Register(WordCountPlugin{})
fmt.Println("Plugins:", reg.List())
input := "Hello innoZverse"
for _, name := range reg.List() {
result, _ := reg.Run(name, input)
fmt.Printf(" %s(%q) = %q\n", name, input, result)
}
}
EOF