interfaces

package
v0.0.0-...-d375c66 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 27, 2025 License: MIT Imports: 17 Imported by: 0

README

Interface Implementation Patterns in Go

This directory demonstrates idiomatic Go interface implementation patterns and best practices. Interfaces in Go are implicitly implemented, which creates unique patterns and approaches compared to explicitly implemented interfaces in other languages.

Understanding Go's Interface Philosophy

Go interfaces are a collection of method signatures that objects can implement implicitly. Unlike languages with explicit interface implementation (e.g., Java, C#), Go types automatically satisfy an interface if they implement all of its methods, without any explicit declaration.

Key Concepts
  • Interfaces are satisfied implicitly
  • Small, focused interfaces are preferred (Interface Segregation)
  • Accept interfaces, return concrete types
  • Composition over inheritance
  • Interfaces foster decoupling and testability

Patterns Implemented

  1. Basic Interface Implementation: Simple interface definition and usage
  2. Interface Composition: Embedding interfaces within other interfaces
  3. Accept Interfaces, Return Structs: Design pattern for flexible functions
  4. Interface Segregation: Small, focused interfaces
  5. Empty Interface Usage: Working with the empty interface and type assertions
  6. Duck Typing in Practice: Leveraging implicit interface satisfaction
  7. Testing with Interfaces: Using interfaces for mocks and stubs
  8. Interface Upgrade Patterns: Evolving interfaces over time
  9. Anti-Patterns: Common interface mistakes to avoid
  10. Standard Library Interface Examples: Real-world interface patterns from Go's standard library

Best Practices

  1. Keep Interfaces Small:

    // Good: Focused interface with a single responsibility
    type Reader interface {
        Read(p []byte) (n int, err error)
    }
    
  2. Use Interface Composition:

    // Building larger interfaces through composition
    type ReadWriter interface {
        Reader
        Writer
    }
    
  3. Accept Interfaces, Return Concrete Types:

    // Accept interface (flexible input)
    func Process(r Reader) *Result {
        // Implementation...
        return &Result{} // Return concrete type
    }
    
  4. Use Interfaces for Seams in Testing:

    // Interfaces make it easy to substitute implementations for testing
    type Service interface {
        FetchData() ([]string, error)
    }
    
  5. Design for the Consumer, Not the Implementation:

    • Define interfaces where they are used, not where types are defined
    • Focus on behavior needed by consumers, not all behaviors provided

Comparison with Inheritance-Based Languages

Go's Interface Approach Inheritance-Based Approach
Implicit implementation Explicit implementation
Composition of behaviors Inheritance hierarchy
Interface at use site Interface at definition site
No "is-a" relationship Strong "is-a" relationship
Duck typing Type checking
Runtime polymorphism Compile-time polymorphism

Testing Interface Implementations

This directory includes tests that demonstrate how to properly test interfaces and their implementations, including:

  • Writing tests with mock implementations
  • Using interface flexibility for test fixtures
  • Testing interface compliance
  • Testing behavior rather than implementation

Documentation

Overview

Package interfaces demonstrates idiomatic Go interface implementation patterns

Package interfaces demonstrates idiomatic Go interface implementation patterns.

Package interfaces demonstrates idiomatic Go interface implementation patterns

Package interfaces demonstrates idiomatic Go interface implementation patterns

Package interfaces demonstrates idiomatic Go interface implementation patterns

Package interfaces demonstrates idiomatic Go interface implementation patterns

Package interfaces demonstrates idiomatic Go interface implementation patterns

Package interfaces demonstrates idiomatic Go interface implementation patterns.

Package interfaces demonstrates idiomatic Go interface implementation patterns

Package interfaces demonstrates idiomatic Go interface implementation patterns

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AcceptReturnDemo

func AcceptReturnDemo()

AcceptReturnDemo demonstrates the "accept interfaces, return structs" pattern

func AdvancedOperation

func AdvancedOperation(rws FileReadWriteSeeker) error

AdvancedOperation requires more capabilities

func BadFactory

func BadFactory() io.Reader

BadFactory returns an interface, forcing the caller to work with a limited view

func BadFunction

func BadFunction(data any) any

BadFunction uses empty interface unnecessarily - generally an anti-pattern

func BasicInterfaceDemo

func BasicInterfaceDemo()

BasicInterfaceDemo demonstrates basic interface implementation in Go

func BetterFunction

func BetterFunction(data string) int

BetterFunction uses concrete types - preferred when possible

func CalculatorDemo

func CalculatorDemo()

CalculatorDemo demonstrates the accept interfaces pattern with calculations

func Collection

func Collection()

Collection demonstrates using empty interface for heterogeneous collections

func CompositionDemo

func CompositionDemo()

CompositionDemo demonstrates interface composition

func ConfigExample

func ConfigExample()

ConfigExample demonstrates the config use case

func CopyData

func CopyData(r FileReader, w FileWriter) (int, error)

CopyData accepts minimal interfaces needed for copying

func CustomSortExample

func CustomSortExample()

CustomSortExample demonstrates implementing sort.Interface

func DemonstrateAntiPatterns

func DemonstrateAntiPatterns()

DemonstrateAntiPatterns shows examples of interface anti-patterns

func DemonstrateStdlibInterfaces

func DemonstrateStdlibInterfaces()

DemonstrateStdlibInterfaces shows all the standard library interface examples

func DisplayProperties

func DisplayProperties(item DisplayItem)

DisplayProperties renders properties for any DisplayItem

func DuckTypingBasics

func DuckTypingBasics()

DuckTypingBasics demonstrates basic duck typing in Go

func DuckTypingDemo

func DuckTypingDemo()

DuckTypingDemo demonstrates duck typing in Go

func EmptyInterfaceDemo

func EmptyInterfaceDemo()

EmptyInterfaceDemo demonstrates the empty interface and type assertions

func ExtendingInterfacesDemo

func ExtendingInterfacesDemo()

ExtendingInterfacesDemo demonstrates extending standard library interfaces

func HttpHandlerExample

func HttpHandlerExample()

HttpHandlerExample demonstrates the http.Handler interface

func IOCompositionExample

func IOCompositionExample()

IOCompositionExample demonstrates interface composition

func InconsistentUsage

func InconsistentUsage()

Usage demonstrates a common mistake

func InterfaceEmbeddingDemo

func InterfaceEmbeddingDemo()

InterfaceEmbeddingDemo demonstrates embedding interfaces in structs

func InterfaceTestingDemo

func InterfaceTestingDemo()

InterfaceTestingDemo demonstrates using interfaces for testing

func InterfaceUpgradeDemo

func InterfaceUpgradeDemo()

InterfaceUpgradeDemo demonstrates interface upgrade patterns

func JSONInterfaceExample

func JSONInterfaceExample()

JSONInterfaceExample demonstrates json.Marshaler and json.Unmarshaler

func LoggingMiddleware

func LoggingMiddleware(next http.Handler) http.Handler

LoggingMiddleware wraps an http.Handler and logs each request

func MethodSetExample

func MethodSetExample()

func MultiLevelCompositionDemo

func MultiLevelCompositionDemo()

MultiLevelCompositionDemo demonstrates multi-level interface composition

func MultipleInterfacesDemo

func MultipleInterfacesDemo()

MultipleInterfacesDemo demonstrates implementing multiple interfaces

func NilInterfaceDemo

func NilInterfaceDemo()

NilInterfaceDemo demonstrates how nil values work with interfaces

func ParseValue

func ParseValue(s string) (any, error)

ParseValue converts a string to various types using the empty interface

func PointerReceiverDemo

func PointerReceiverDemo()

PointerReceiverDemo demonstrates interface implementation with pointer receivers

func PrintItems

func PrintItems(items []Stringable)

PrintItems prints any slice of items that implement Stringable

func PrintReflection

func PrintReflection(v any)

PrintReflection uses reflection to inspect a value of any type

func ReadOnly

func ReadOnly(r FileReader) ([]byte, error)

ReadOnly accepts only a Reader, demonstrating that we can constrain functions to only require the minimal interface they need

func ReaderWriterExample

func ReaderWriterExample()

ReaderWriterExample shows the power of the io.Reader and io.Writer interfaces

func ReturningInterfacesDemo

func ReturningInterfacesDemo()

ReturningInterfacesDemo shows when it makes sense to return an interface

func RunAcceptReturnDemo

func RunAcceptReturnDemo()

RunAcceptReturnDemo demonstrates all aspects of the "accept interfaces, return structs" pattern

func RunConcurrencyExample

func RunConcurrencyExample()

RunConcurrencyExample demonstrates the difference between safe and unsafe implementations

func SegregationDemo

func SegregationDemo()

SegregationDemo demonstrates the interface segregation principle

func ShowAdapterPattern

func ShowAdapterPattern()

ShowAdapterPattern demonstrates the adapter pattern for interface upgrades

func ShowDeprecatedFunction

func ShowDeprecatedFunction()

ShowDeprecatedFunction demonstrates upgrading with deprecated functions

func ShowV1

func ShowV1()

ShowV1 demonstrates the V1 interface

func ShowV2

func ShowV2()

ShowV2 demonstrates the V2 interface

func ShowV3

func ShowV3()

ShowV3 demonstrates the V3 interface with context

func SortData

func SortData()

SortData demonstrates another example of accepting interfaces

func SortInterfaceExample

func SortInterfaceExample()

SortInterfaceExample demonstrates the power of sort.Interface

func StringSorter

func StringSorter(r io.Reader) (string, error)

StringSorter creates a function that sorts lines in a string

func StructuralVsNominalTyping

func StructuralVsNominalTyping()

StructuralVsNominalTyping demonstrates the difference between Go's structural typing vs nominal typing in other languages

func TestCreateUser

func TestCreateUser()

TestCreateUser demonstrates how to test with mock dependencies

func TestDeleteUser

func TestDeleteUser()

TestDeleteUser demonstrates more advanced testing with mocks

func TypeAssertionBasics

func TypeAssertionBasics()

TypeAssertionBasics demonstrates basic type assertions

func TypeSwitchExample

func TypeSwitchExample(value any)

TypeSwitchExample demonstrates using type switches

func UnsafeTypeAssertions

func UnsafeTypeAssertions(value interface{})

UnsafeTypeAssertions demonstrates dangerous type assertions

func UseCounter

func UseCounter(c Counter)

func UseLogger

func UseLogger(logger Loggable, message string)

UseLogger demonstrates using a logger without tight coupling

func UseShape

func UseShape(s Shape)

UseShape demonstrates using a function that accepts an interface

func UsingGenericHolder

func UsingGenericHolder()

Usage requires type assertions and can lead to runtime errors

func UsingTypedHolder

func UsingTypedHolder()

Usage is type-safe and prevents runtime errors

func WriteOnly

func WriteOnly(w FileWriter, data []byte) error

WriteOnly accepts only a Writer

Types

type Adder

type Adder struct{}

Adder implements Calculator by adding numbers

func (Adder) Calculate

func (a Adder) Calculate(x, y int) int

Calculate implements the Calculator interface

type AdvancedStorage

type AdvancedStorage struct {
	*EnhancedStorage // Embed V2 implementation
}

AdvancedStorage implements the V3 interface

func NewAdvancedStorage

func NewAdvancedStorage() *AdvancedStorage

NewAdvancedStorage creates a new AdvancedStorage

func (*AdvancedStorage) DeleteWithContext

func (s *AdvancedStorage) DeleteWithContext(ctx context.Context, key string) error

DeleteWithContext deletes a value with context support

func (*AdvancedStorage) GetWithContext

func (s *AdvancedStorage) GetWithContext(ctx context.Context, key string) ([]byte, error)

GetWithContext gets a value with context support

func (*AdvancedStorage) SetWithContext

func (s *AdvancedStorage) SetWithContext(ctx context.Context, key string, value []byte) error

SetWithContext sets a value with context support

type BadDatabaseClient

type BadDatabaseClient interface {
	Connect(connectionString string) error
	Disconnect() error
	Query(query string) ([]byte, error)
	Execute(command string) error
	BeginTransaction() error
	CommitTransaction() error
	RollbackTransaction() error
	CacheResults(key string, data []byte) error
	GetFromCache(key string) ([]byte, error)
	ValidateSchema() error
	MigrateDatabase() error
	LogQuery(query string) error
	Authenticate(username, password string) error
	CheckPermissions(user string, resource string) bool
}

BadDatabaseClient is an example of a "fat interface" - it has too many methods and combines multiple responsibilities.

type BadInterfaceEmbedding

type BadInterfaceEmbedding struct {
	io.Writer // Embedding interface without implementing Write method
	// contains filtered or unexported fields
}

BadInterfaceEmbedding embeds the io.Writer interface but doesn't implement its methods

type BufferedWriteCloser

type BufferedWriteCloser struct {
	*bufio.Writer
	io.Closer
}

BufferedWriteCloser combines a buffered writer with a closer

func NewBufferedWriteCloser

func NewBufferedWriteCloser(w io.WriteCloser, size int) *BufferedWriteCloser

NewBufferedWriteCloser creates a new BufferedWriteCloser

func (*BufferedWriteCloser) Close

func (bwc *BufferedWriteCloser) Close() error

Close flushes the buffer and closes the underlying writer

type ByAge

type ByAge []Person

ByAge implements sort.Interface for []Person based on Age field

func (ByAge) Len

func (a ByAge) Len() int

func (ByAge) Less

func (a ByAge) Less(i, j int) bool

func (ByAge) Swap

func (a ByAge) Swap(i, j int)

type ByName

type ByName []Person

ByName implements sort.Interface for []Person based on Name field

func (ByName) Len

func (a ByName) Len() int

func (ByName) Less

func (a ByName) Less(i, j int) bool

func (ByName) Swap

func (a ByName) Swap(i, j int)

type CachingService

type CachingService struct {
	DataStore // Interface embedding in struct
	// contains filtered or unexported fields
}

CachingService embeds a DataStore interface This demonstrates embedding an interface inside a struct

func NewCachingService

func NewCachingService(store DataStore) *CachingService

NewCachingService creates a new CachingService

func (*CachingService) CacheMisses

func (c *CachingService) CacheMisses() int

CacheMisses returns the number of cache misses

func (*CachingService) Get

func (c *CachingService) Get(key string) (string, bool)

Get overrides the embedded Get method to add caching

type CalculationResult

type CalculationResult struct {
	Input1     int
	Input2     int
	Result     int
	Operation  string
	IsPositive bool
}

CalculationResult is a concrete return type

func PerformCalculation

func PerformCalculation(calc Calculator, a, b int) *CalculationResult

PerformCalculation demonstrates the pattern with calculations

type Calculator

type Calculator interface {
	Calculate(a, b int) int
}

Calculator defines calculation behavior

type Circle

type Circle struct {
	Radius float64
}

Circle is a concrete type that implicitly implements the Shape interface

func (Circle) Area

func (c Circle) Area() float64

Area calculates the area of a circle This method means Circle implicitly implements the Shape interface

func (Circle) Describe

func (c Circle) Describe() string

Describe returns a description of the circle

type ClientV1

type ClientV1 struct {
	// contains filtered or unexported fields
}

ClientV1 uses the V1 interface

func NewClientV1

func NewClientV1(storage StorageV1) *ClientV1

NewClientV1 creates a new ClientV1

func (*ClientV1) GetData

func (c *ClientV1) GetData(key string) ([]byte, error)

GetData retrieves data using V1 interface

func (*ClientV1) StoreData

func (c *ClientV1) StoreData(key string, value []byte) error

StoreData stores data using V1 interface

type ClientV2

type ClientV2 struct {
	// contains filtered or unexported fields
}

ClientV2 uses the V2 interface

func NewClientV2

func NewClientV2(storage StorageV2) *ClientV2

NewClientV2 creates a new ClientV2

func (*ClientV2) GetData

func (c *ClientV2) GetData(key string) ([]byte, time.Time, error)

GetData retrieves data checking expiration

func (*ClientV2) ListData

func (c *ClientV2) ListData(prefix string) ([]string, error)

ListData lists keys with a prefix

func (*ClientV2) StoreData

func (c *ClientV2) StoreData(key string, value []byte, expiration time.Duration) error

StoreData stores data with expiration

type ClientV3

type ClientV3 struct {
	// contains filtered or unexported fields
}

ClientV3 uses the V3 interface

func NewClientV3

func NewClientV3(storage StorageV3) *ClientV3

NewClientV3 creates a new ClientV3

func (*ClientV3) GetData

func (c *ClientV3) GetData(ctx context.Context, key string) ([]byte, error)

GetData retrieves data with context

func (*ClientV3) StoreData

func (c *ClientV3) StoreData(ctx context.Context, key string, value []byte) error

StoreData stores data with context

type Closer

type Closer interface {
	Close() error
}

Closer is an interface for types that can be closed

type CombinedLogger

type CombinedLogger struct {
	// contains filtered or unexported fields
}

Implementation of both interfaces

func NewCombinedLogger

func NewCombinedLogger(output io.Writer) *CombinedLogger

NewCombinedLogger creates a new CombinedLogger

func (*CombinedLogger) Log

func (l *CombinedLogger) Log(message string)

Log implements LoggerV1.Log (deprecated)

func (*CombinedLogger) LogError

func (l *CombinedLogger) LogError(err error)

LogError implements LoggerV1.LogError (deprecated)

func (*CombinedLogger) LogErrorWithLevel

func (l *CombinedLogger) LogErrorWithLevel(level string, err error)

LogErrorWithLevel implements LoggerV2.LogErrorWithLevel

func (*CombinedLogger) LogWithLevel

func (l *CombinedLogger) LogWithLevel(level string, message string)

LogWithLevel implements LoggerV2.LogWithLevel

type CombinedStorage

type CombinedStorage struct {
	StorageV2
	StorageV3Alt
}

Wrapper to combine both V2 and V3Alt capabilities

type ConcreteReader

type ConcreteReader struct {
	// contains filtered or unexported fields
}

ConcreteReader is an implementation of io.Reader

func BetterFactory

func BetterFactory() *ConcreteReader

BetterFactory returns a concrete type, giving callers access to all methods

func (*ConcreteReader) AdditionalMethod

func (r *ConcreteReader) AdditionalMethod() string

AdditionalMethod is a useful method that's hidden when returning just an io.Reader

func (*ConcreteReader) Read

func (r *ConcreteReader) Read(p []byte) (n int, err error)

Read implements the io.Reader interface

type Config

type Config map[string]any

Config demonstrates a simple configuration using map[string]any

func (Config) GetInt

func (c Config) GetInt(key string, defaultVal int) int

GetInt safely gets an int from the config

func (Config) GetString

func (c Config) GetString(key string, defaultVal string) string

GetString safely gets a string from the config

func (Config) GetStringList

func (c Config) GetStringList(key string, defaultVal []string) []string

GetStringList safely gets a string slice from the config

type Connectable

type Connectable interface {
	Connect(connectionString string) error
	Disconnect() error
}

type CorrectInterfaceEmbedding

type CorrectInterfaceEmbedding struct {
	// contains filtered or unexported fields
}

CorrectInterfaceEmbedding properly embeds and implements the interface

func (*CorrectInterfaceEmbedding) Write

func (c *CorrectInterfaceEmbedding) Write(p []byte) (n int, err error)

type Counter

type Counter interface {
	Count() int
}

Counter interface captures counting behavior

type CustomTime

type CustomTime struct {
	time.Time
}

CustomTime demonstrates implementing json.Marshaler and json.Unmarshaler

func (CustomTime) MarshalJSON

func (ct CustomTime) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for custom time formatting

func (*CustomTime) UnmarshalJSON

func (ct *CustomTime) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler for custom time parsing

type DataProcessor

type DataProcessor interface {
	Process(data string) string
}

DataProcessor represents something that can process data

func NewProcessor

func NewProcessor(prefix string) DataProcessor

NewProcessor creates a new processor with the given prefix This function returns an interface, which is acceptable when: 1. You want to hide implementation details 2. You need polymorphic behavior determined at runtime

type DataStore

type DataStore interface {
	Get(id string) ([]byte, error)
	Set(id string, data []byte) error
	Delete(id string) error
}

DataStore defines the interface for data storage operations

type DatabaseUserRepository

type DatabaseUserRepository struct {
	// contains filtered or unexported fields
}

DatabaseUserRepository is a real implementation of UserRepository

func NewDatabaseUserRepository

func NewDatabaseUserRepository(db DataStore) *DatabaseUserRepository

NewDatabaseUserRepository creates a new DatabaseUserRepository

func (*DatabaseUserRepository) Delete

func (r *DatabaseUserRepository) Delete(id string) error

Delete removes a user from the database

func (*DatabaseUserRepository) FindByID

func (r *DatabaseUserRepository) FindByID(id string) (*User, error)

FindByID retrieves a user from the database

func (*DatabaseUserRepository) Save

func (r *DatabaseUserRepository) Save(user *User) error

Save stores a user in the database

type Describer

type Describer interface {
	Describe() string
}

Describer is an interface for types that can describe themselves

type DisplayItem

type DisplayItem interface {
	Properties() map[string]string
}

DisplayItem is an interface that only requires Properties() method

type Duck

type Duck struct {
	Name string
}

Duck is a concrete type that naturally quacks

func (Duck) Quack

func (d Duck) Quack() string

Quack makes the duck quack

type EmailRecord

type EmailRecord struct {
	To      string
	Subject string
	Body    string
}

EmailRecord represents a sent email

type EmailService

type EmailService interface {
	SendEmail(to, subject, body string) error
}

EmailService defines the interface for sending emails

type EnhancedStorage

type EnhancedStorage struct {
	SimpleStorage // Embed V1 implementation
	// contains filtered or unexported fields
}

EnhancedStorage implements the V2 interface

func NewEnhancedStorage

func NewEnhancedStorage() *EnhancedStorage

NewEnhancedStorage creates a new EnhancedStorage

func (*EnhancedStorage) GetWithExpiration

func (s *EnhancedStorage) GetWithExpiration(key string) ([]byte, time.Time, error)

GetWithExpiration retrieves a value and its expiration time

func (*EnhancedStorage) List

func (s *EnhancedStorage) List(prefix string) ([]string, error)

List returns all keys with the given prefix

func (*EnhancedStorage) SetWithExpiration

func (s *EnhancedStorage) SetWithExpiration(key string, value []byte, expiration time.Duration) error

SetWithExpiration stores a value with an expiration time

type Event

type Event struct {
	Title string     `json:"title"`
	Time  CustomTime `json:"time"`
}

Event represents an event with a title and timestamp

type File

type File struct {
	Name     string
	Size     int
	Location string
}

File implements DisplayItem

func (File) Properties

func (f File) Properties() map[string]string

type FileCloser

type FileCloser interface {
	Close() error
}

Closer is an interface for closing resources

type FileInfo

type FileInfo interface {
	Name() string
	Size() int64
	IsDir() bool
	ModTime() time.Time
}

FileInfo is a simple interface representing file information

type FileManager

type FileManager interface {
	Read(p []byte) (n int, err error)
	Write(p []byte) (n int, err error)
	Seek(offset int64, whence int) (int64, error)
	Close() error
	Stat() (FileInfo, error)
	Chmod(mode uint32) error
	Chown(uid, gid int) error
	Truncate(size int64) error
	Sync() error
}

FileManager is a monolithic interface that handles many different operations This violates interface segregation and is shown as an anti-pattern

type FilePermissionsManager

type FilePermissionsManager interface {
	Chmod(mode uint32) error
	Chown(uid, gid int) error
}

FilePermissionsManager handles file permissions

type FileReadSeeker

type FileReadSeeker interface {
	FileReader
	FileSeeker
}

ReadSeeker combines read and seek capabilities

type FileReadWriteCloser

type FileReadWriteCloser interface {
	FileReader
	FileWriter
	FileCloser
}

ReadWriteCloser adds closing capability

type FileReadWriteSeeker

type FileReadWriteSeeker interface {
	FileReader
	FileWriter
	FileSeeker
}

ReadWriteSeeker combines read, write and seek capabilities

type FileReadWriter

type FileReadWriter interface {
	FileReader
	FileWriter
}

ReadWriter combines read and write capabilities

type FileReader

type FileReader interface {
	Read(p []byte) (n int, err error)
}

Reader is an interface for reading data

type FileSeeker

type FileSeeker interface {
	Seek(offset int64, whence int) (int64, error)
}

Seeker is an interface for seeking within a file

type FileSyncer

type FileSyncer interface {
	Sync() error
}

FileSyncer handles syncing file to disk

type FileTruncater

type FileTruncater interface {
	Truncate(size int64) error
}

FileTruncater handles file truncation

type FileWriter

type FileWriter interface {
	Write(p []byte) (n int, err error)
}

Writer is an interface for writing data

type GenericContainer

type GenericContainer struct {
	Value any // empty interface (interface{} in earlier Go versions)
}

GenericContainer demonstrates using the empty interface to store any type

func (GenericContainer) Print

func (c GenericContainer) Print()

Print prints the container value, handling different types

type GenericHolder

type GenericHolder struct {
	// contains filtered or unexported fields
}

GenericHolder overuses empty interface

func NewGenericHolder

func NewGenericHolder() *GenericHolder

func (*GenericHolder) Get

func (h *GenericHolder) Get(key string) interface{}

func (*GenericHolder) Set

func (h *GenericHolder) Set(key string, value interface{})

type HelloHandler

type HelloHandler struct {
	Greeting string
}

HelloHandler is a simple implementation of http.Handler

func (HelloHandler) ServeHTTP

func (h HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Inconsistent

type Inconsistent interface {
	Method1()
	Method2()
}

Inconsistent is an example interface

type InconsistentImpl

type InconsistentImpl struct {
	// contains filtered or unexported fields
}

InconsistentImpl mixes pointer and value receivers

func (*InconsistentImpl) Method1

func (i *InconsistentImpl) Method1()

Method1 uses a pointer receiver

func (InconsistentImpl) Method2

func (i InconsistentImpl) Method2()

Method2 uses a value receiver

type InterfacePromise

type InterfacePromise interface {
	Fulfill() (string, error)
}

InterfacePromise represents a promise to provide data

type Loggable

type Loggable interface {
	Log(message string)
}

Loggable is an interface for anything that can log

type Logger

type Logger struct {
	Prefix string
}

Logger provides logging functionality

func (Logger) Log

func (l Logger) Log(message string)

type LoggerV1

type LoggerV1 interface {
	Log(message string)
	LogError(err error)
}

Original interface

type LoggerV2

type LoggerV2 interface {
	LogWithLevel(level string, message string)
	LogErrorWithLevel(level string, err error)
}

Updated interface

type LoggingReader

type LoggingReader struct {
	// contains filtered or unexported fields
}

LoggingReader adds logging to any Reader

func NewLoggingReader

func NewLoggingReader(r Reader, operation string) *LoggingReader

NewLoggingReader creates a new LoggingReader

func (*LoggingReader) Read

func (lr *LoggingReader) Read(p []byte) (n int, err error)

Read implements the Reader interface and adds logging

type MockEmailService

type MockEmailService struct {
	// contains filtered or unexported fields
}

MockEmailService is a test double for EmailService

func NewMockEmailService

func NewMockEmailService() *MockEmailService

NewMockEmailService creates a new MockEmailService

func (*MockEmailService) GetSentEmails

func (m *MockEmailService) GetSentEmails() []EmailRecord

GetSentEmails returns all sent emails

func (*MockEmailService) SendEmail

func (m *MockEmailService) SendEmail(to, subject, body string) error

SendEmail implements EmailService.SendEmail for testing

func (*MockEmailService) SetShouldError

func (m *MockEmailService) SetShouldError(shouldErr bool)

SetShouldError configures whether the mock should return an error

type MockFile

type MockFile struct {
	// contains filtered or unexported fields
}

MockFile implements multiple interfaces through composition

func NewMockFile

func NewMockFile(name string, data []byte) *MockFile

NewMockFile creates a new MockFile

func (*MockFile) Chmod

func (f *MockFile) Chmod(mode uint32) error

Chmod implements part of FilePermissionsManager

func (*MockFile) Chown

func (f *MockFile) Chown(uid, gid int) error

Chown implements part of FilePermissionsManager

func (*MockFile) Close

func (f *MockFile) Close() error

Close implements FileCloser

func (*MockFile) Read

func (f *MockFile) Read(p []byte) (int, error)

Read implements FileReader

func (*MockFile) Seek

func (f *MockFile) Seek(offset int64, whence int) (int64, error)

Seek implements FileSeeker

func (*MockFile) Stat

func (f *MockFile) Stat() (FileInfo, error)

Stat implements StatProvider

func (*MockFile) Sync

func (f *MockFile) Sync() error

Sync implements FileSyncer

func (*MockFile) Truncate

func (f *MockFile) Truncate(size int64) error

Truncate implements FileTruncater

func (*MockFile) Write

func (f *MockFile) Write(p []byte) (int, error)

Write implements FileWriter

type MockUserRepository

type MockUserRepository struct {
	// contains filtered or unexported fields
}

MockUserRepository is a test double for UserRepository

func NewMockUserRepository

func NewMockUserRepository() *MockUserRepository

NewMockUserRepository creates a new MockUserRepository

func (*MockUserRepository) AddUser

func (m *MockUserRepository) AddUser(user *User)

AddUser adds a user to the mock repository

func (*MockUserRepository) Delete

func (m *MockUserRepository) Delete(id string) error

Delete implements UserRepository.Delete for testing

func (*MockUserRepository) FindByID

func (m *MockUserRepository) FindByID(id string) (*User, error)

FindByID implements UserRepository.FindByID for testing

func (*MockUserRepository) GetDeleteCount

func (m *MockUserRepository) GetDeleteCount() int

GetDeleteCount returns the number of times Delete was called

func (*MockUserRepository) GetFindCount

func (m *MockUserRepository) GetFindCount() int

GetFindCount returns the number of times FindByID was called

func (*MockUserRepository) GetSaveCount

func (m *MockUserRepository) GetSaveCount() int

GetSaveCount returns the number of times Save was called

func (*MockUserRepository) Save

func (m *MockUserRepository) Save(user *User) error

Save implements UserRepository.Save for testing

func (*MockUserRepository) SetDeleteError

func (m *MockUserRepository) SetDeleteError(err error)

SetDeleteError sets an error to be returned by Delete

func (*MockUserRepository) SetFindError

func (m *MockUserRepository) SetFindError(err error)

SetFindError sets an error to be returned by FindByID

func (*MockUserRepository) SetSaveError

func (m *MockUserRepository) SetSaveError(err error)

SetSaveError sets an error to be returned by Save

type Moveable

type Moveable interface {
	Move(dx, dy float64)
	Position() (x, y float64)
}

Moveable is an interface for things that can move

type Mover

type Mover interface {
	Move(dx, dy float64)
	GetPosition() (float64, float64)
}

Mover is an interface for things that can move

type Multiplier

type Multiplier struct{}

Multiplier implements Calculator by multiplying numbers

func (Multiplier) Calculate

func (m Multiplier) Calculate(x, y int) int

Calculate implements the Calculator interface

type Order

type Order struct {
	OrderID   string
	Products  []Product
	Total     float64
	Completed bool
}

func (Order) ToString

func (o Order) ToString() string

type Person

type Person struct {
	Name string
	Age  int
}

Person represents a person with a name and age

func (Person) Quack

func (p Person) Quack() string

Quack makes the person imitate a duck This means Person implicitly satisfies the Quacker interface

type Point

type Point struct {
	X, Y float64
}

Point is a struct representing a 2D point

func (Point) GetPosition

func (p Point) GetPosition() (float64, float64)

GetPosition returns the current position

func (*Point) Move

func (p *Point) Move(dx, dy float64)

Move changes the point's position (requires a pointer receiver to modify the struct)

type Point2D

type Point2D struct {
	X, Y float64
}

Point satisfies Moveable

func (*Point2D) Move

func (p *Point2D) Move(dx, dy float64)

func (Point2D) Position

func (p Point2D) Position() (x, y float64)

type PointerReceiverOnly

type PointerReceiverOnly struct {
	// contains filtered or unexported fields
}

PointerReceiverOnly has methods with pointer receivers

func (*PointerReceiverOnly) Count

func (p *PointerReceiverOnly) Count() int

func (*PointerReceiverOnly) Increment

func (p *PointerReceiverOnly) Increment()

type Product

type Product struct {
	ID    int
	Name  string
	Price float64
}

func (Product) ToString

func (p Product) ToString() string

type Quacker

type Quacker interface {
	Quack() string
}

Quacker is an interface for things that can quack

type Queryable

type Queryable interface {
	Query(query string) ([]byte, error)
}

Better approach: Use smaller, focused interfaces with specific responsibilities

type ReadWriteCloser

type ReadWriteCloser interface {
	Reader
	Writer
	Closer
}

ReadWriteCloser composes three interfaces

type ReadWriter

type ReadWriter interface {
	Reader
	Writer
}

ReadWriter composes the Reader and Writer interfaces This is interface embedding - a fundamental form of composition in Go

type Reader

type Reader interface {
	Read(p []byte) (n int, err error)
}

Reader is an interface for types that can read data

type ReaderToStringable

type ReaderToStringable struct {
	Name string
	// contains filtered or unexported fields
}

Wrapper to adapt existing types to new interfaces

func (ReaderToStringable) ToString

func (r ReaderToStringable) ToString() string

type Rectangle

type Rectangle struct {
	Width, Height float64
}

Rectangle is another concrete type that implicitly implements the Shape interface

func (Rectangle) Area

func (r Rectangle) Area() float64

Area calculates the area of a rectangle This method means Rectangle implicitly implements the Shape interface

func (Rectangle) Describe

func (r Rectangle) Describe() string

Describe returns a description of the rectangle

type Result

type Result struct {
	Data       string
	LineCount  int
	WordCount  int
	ByteCount  int
	IsModified bool
}

Result is a concrete type returned by our functions

func DataLoader

func DataLoader(promise InterfacePromise) (*Result, error)

DataLoader loads data from a promise and transforms it

func ProcessData

func ProcessData(processor DataProcessor, data string) *Result

ProcessData accepts an interface and returns a struct This demonstrates the "accept interfaces, return structs" pattern

type SafeCounter

type SafeCounter struct {
	// contains filtered or unexported fields
}

SafeCounter is safe for concurrent use

func (*SafeCounter) GetCount

func (c *SafeCounter) GetCount() int

func (*SafeCounter) Increment

func (c *SafeCounter) Increment()

type Service

type Service struct {
	Name   string
	Logger // Embed Logger struct
}

Service uses logging capability via embedding

type Shape

type Shape interface {
	Area() float64
}

Shape is a basic interface that defines a method for calculating area

type SimpleProcessor

type SimpleProcessor struct {
	// contains filtered or unexported fields
}

SimpleProcessor is a basic implementation of DataProcessor

func (SimpleProcessor) Process

func (p SimpleProcessor) Process(data string) string

Process implements the DataProcessor interface

type SimpleStorage

type SimpleStorage struct {
	// contains filtered or unexported fields
}

SimpleStorage implements the V1 interface

func NewSimpleStorage

func NewSimpleStorage() *SimpleStorage

NewSimpleStorage creates a new SimpleStorage

func (*SimpleStorage) Delete

func (s *SimpleStorage) Delete(key string) error

Delete removes a value from storage

func (*SimpleStorage) Get

func (s *SimpleStorage) Get(key string) ([]byte, error)

Get retrieves a value from storage

func (*SimpleStorage) Set

func (s *SimpleStorage) Set(key string, value []byte) error

Set stores a value in storage

type SimpleStore

type SimpleStore struct {
	// contains filtered or unexported fields
}

SimpleStore is a basic implementation of DataStore

func NewSimpleStore

func NewSimpleStore() *SimpleStore

NewSimpleStore creates a new SimpleStore

func (*SimpleStore) Get

func (s *SimpleStore) Get(key string) (string, bool)

Get retrieves a value from the store

func (*SimpleStore) Set

func (s *SimpleStore) Set(key, value string)

Set stores a value in the store

type SmtpEmailService

type SmtpEmailService struct {
	// contains filtered or unexported fields
}

SmtpEmailService is a real implementation of EmailService

func NewSmtpEmailService

func NewSmtpEmailService(server string, port int, username, password string) *SmtpEmailService

NewSmtpEmailService creates a new SmtpEmailService

func (*SmtpEmailService) SendEmail

func (s *SmtpEmailService) SendEmail(to, subject, body string) error

SendEmail sends an email via SMTP

type SortableString

type SortableString string

SortableString is just a string that knows how to sort itself

type SortableStringSlice

type SortableStringSlice []SortableString

We can implement sort.Interface methods on any type

func (SortableStringSlice) Len

func (s SortableStringSlice) Len() int

func (SortableStringSlice) Less

func (s SortableStringSlice) Less(i, j int) bool

func (SortableStringSlice) Swap

func (s SortableStringSlice) Swap(i, j int)

type StatProvider

type StatProvider interface {
	Stat() (FileInfo, error)
}

StatProvider provides file information

type StorageAdapter

type StorageAdapter struct {
	// contains filtered or unexported fields
}

StorageAdapter adapts V2 to V3Alt

func NewStorageAdapter

func NewStorageAdapter(v2 StorageV2) *StorageAdapter

NewStorageAdapter creates a new adapter

func (*StorageAdapter) DeleteWithContext

func (a *StorageAdapter) DeleteWithContext(ctx context.Context, key string) error

DeleteWithContext implements StorageV3Alt

func (*StorageAdapter) GetWithContext

func (a *StorageAdapter) GetWithContext(ctx context.Context, key string) ([]byte, error)

GetWithContext implements StorageV3Alt

func (*StorageAdapter) SetWithContext

func (a *StorageAdapter) SetWithContext(ctx context.Context, key string, value []byte) error

SetWithContext implements StorageV3Alt

type StorageV1

type StorageV1 interface {
	Get(key string) ([]byte, error)
	Set(key string, value []byte) error
	Delete(key string) error
}

StorageV1 is the first version of our storage interface

type StorageV2

type StorageV2 interface {
	StorageV1 // Embed V1 interface for backward compatibility
	GetWithExpiration(key string) ([]byte, time.Time, error)
	SetWithExpiration(key string, value []byte, expiration time.Duration) error
	List(prefix string) ([]string, error)
}

StorageV2 extends StorageV1 with new capabilities

type StorageV3

type StorageV3 interface {
	// Keep original methods
	Get(key string) ([]byte, error)
	Set(key string, value []byte) error
	Delete(key string) error
	GetWithExpiration(key string) ([]byte, time.Time, error)
	SetWithExpiration(key string, value []byte, expiration time.Duration) error
	List(prefix string) ([]string, error)

	// Context-aware methods
	GetWithContext(ctx context.Context, key string) ([]byte, error)
	SetWithContext(ctx context.Context, key string, value []byte) error
	DeleteWithContext(ctx context.Context, key string) error
}

StorageV3 adds context support to our storage interface

type StorageV3Alt

type StorageV3Alt interface {
	GetWithContext(ctx context.Context, key string) ([]byte, error)
	SetWithContext(ctx context.Context, key string, value []byte) error
	DeleteWithContext(ctx context.Context, key string) error
}

StorageV3Alt is a simpler interface that only defines new context methods

type StringReadWriteCloser

type StringReadWriteCloser struct {
	StringReadWriter
	// contains filtered or unexported fields
}

StringReadWriteCloser implements the ReadWriteCloser interface

func (*StringReadWriteCloser) Close

func (s *StringReadWriteCloser) Close() error

Close implements the Closer interface

func (*StringReadWriteCloser) Read

func (s *StringReadWriteCloser) Read(p []byte) (n int, err error)

Read overrides the embedded Read method to check if closed

func (*StringReadWriteCloser) Write

func (s *StringReadWriteCloser) Write(p []byte) (n int, err error)

Write overrides the embedded Write method to check if closed

type StringReadWriter

type StringReadWriter struct {
	// contains filtered or unexported fields
}

StringReadWriter is a concrete type that implements the ReadWriter interface

func (*StringReadWriter) Read

func (s *StringReadWriter) Read(p []byte) (n int, err error)

Read implements the Reader interface

func (*StringReadWriter) Write

func (s *StringReadWriter) Write(p []byte) (n int, err error)

Write implements the Writer interface

type StringSource

type StringSource struct {
	// contains filtered or unexported fields
}

StringSource is a simple implementation of InterfacePromise

func (StringSource) Fulfill

func (s StringSource) Fulfill() (string, error)

Fulfill implements the InterfacePromise interface

type Stringable

type Stringable interface {
	ToString() string
}

Stringable is an interface for anything that can be converted to a string

type StringerValue

type StringerValue struct {
	Data string
}

StringerValue is an example type that implements fmt.Stringer

func (StringerValue) String

func (s StringerValue) String() string

String implements fmt.Stringer

type Transactional

type Transactional interface {
	BeginTransaction() error
	CommitTransaction() error
	RollbackTransaction() error
}

type TypedHolder

type TypedHolder[T any] struct {
	// contains filtered or unexported fields
}

TypedHolder uses generics for better type safety

func NewTypedHolder

func NewTypedHolder[T any]() *TypedHolder[T]

func (*TypedHolder[T]) Get

func (h *TypedHolder[T]) Get(key string) (T, bool)

func (*TypedHolder[T]) Set

func (h *TypedHolder[T]) Set(key string, value T)

type UnnecessaryRepositoryInterface

type UnnecessaryRepositoryInterface interface {
	GetUserByID(id int) (User, error)
	CreateUser(user User) error
	UpdateUser(user User) error
	DeleteUser(id int) error
}

UnnecessaryRepositoryInterface is an example of an interface created unnecessarily before there are multiple implementations or a need for abstraction

type UnsafeCounter

type UnsafeCounter struct {
	// contains filtered or unexported fields
}

UnsafeCounter is not safe for concurrent use

func (*UnsafeCounter) GetCount

func (c *UnsafeCounter) GetCount() int

func (*UnsafeCounter) Increment

func (c *UnsafeCounter) Increment()

type User

type User struct {
	ID       string
	Username string
	Email    string
	Created  time.Time
}

User represents a user in the system

func (User) ToString

func (u User) ToString() string

type UserRepository

type UserRepository interface {
	FindByID(id string) (*User, error)
	Save(user *User) error
	Delete(id string) error
}

UserRepository handles user data operations

func (*UserRepository) CreateUser

func (r *UserRepository) CreateUser(user User) error

CreateUser adds a new user to storage

func (*UserRepository) DeleteUser

func (r *UserRepository) DeleteUser(id int) error

DeleteUser removes a user from storage

func (*UserRepository) GetUserByID

func (r *UserRepository) GetUserByID(id int) (User, error)

GetUserByID gets a user from storage

func (*UserRepository) UpdateUser

func (r *UserRepository) UpdateUser(user User) error

UpdateUser updates an existing user

type UserService

type UserService struct {
	// contains filtered or unexported fields
}

UserService implements business logic for user operations

func NewUserService

func NewUserService(repo UserRepository, email EmailService) *UserService

NewUserService creates a new UserService

func (*UserService) CreateUser

func (s *UserService) CreateUser(username, email string) (*User, error)

CreateUser creates a new user and sends a welcome email

func (*UserService) DeleteUser

func (s *UserService) DeleteUser(id string) error

DeleteUser deletes a user and sends a confirmation email

func (*UserService) GetUser

func (s *UserService) GetUser(id string) (*User, error)

GetUser retrieves a user by ID

type ValueReceiverOnly

type ValueReceiverOnly struct {
	// contains filtered or unexported fields
}

ValueReceiverOnly has methods with value receivers

func (ValueReceiverOnly) Count

func (v ValueReceiverOnly) Count() int

type WebPage

type WebPage struct {
	URL     string
	Title   string
	Content string
}

WebPage implements DisplayItem

func (WebPage) Properties

func (w WebPage) Properties() map[string]string

type Writer

type Writer interface {
	Write(p []byte) (n int, err error)
}

Writer is an interface for types that can write data

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL