DEV Community

Russell Jones
Russell Jones

Posted on • Originally published at jonesrussell.github.io on

Understanding Go Interfaces: A Practical Guide

Ahnii!

Interfaces in Go might seem simple at first, but they're incredibly powerful. This post explores how to use them effectively and avoid common pitfalls.

What Makes Go Interfaces Special?

Unlike other languages, Go interfaces are:

  • Implicitly implemented
  • Small by convention
  • Composable
  • Type-safe

Basic Interface Usage

Here's a simple example:

// Define a simple interface
type Writer interface {
    Write([]byte) (int, error)
}

// Concrete implementation
type FileWriter struct {
    file *os.File
}

// Implement the Writer interface
func (fw *FileWriter) Write(data []byte) (int, error) {
    return fw.file.Write(data)
}
Enter fullscreen mode Exit fullscreen mode

Interface Best Practices

  1. Keep Interfaces Small
// Good
type Reader interface {
    Read(p []byte) (n int, err error)
}

// Too big
type BigInterface interface {
    Read(p []byte) (n int, err error)
    Write(p []byte) (n int, err error)
    Close() error
    Flush() error
    // ... many more methods
}
Enter fullscreen mode Exit fullscreen mode
  1. Accept Interfaces, Return Structs
// Good
func ProcessData(r Reader) error {
    // ...
}

// Not as flexible
func ProcessData(f *os.File) error {
    // ...
}
Enter fullscreen mode Exit fullscreen mode

Common Interface Patterns

  1. The io.Reader/Writer Family
type ReadWriter interface {
    Reader
    Writer
}
Enter fullscreen mode Exit fullscreen mode
  1. The Stringer Interface
type Stringer interface {
    String() string
}
Enter fullscreen mode Exit fullscreen mode

Testing with Interfaces

Interfaces make testing easier:

type MockWriter struct {
    WrittenData []byte
}

func (m *MockWriter) Write(data []byte) (int, error) {
    m.WrittenData = append(m.WrittenData, data...)
    return len(data), nil
}
Enter fullscreen mode Exit fullscreen mode

Real-World Examples

Here's how interfaces solve common problems:

  1. Database Abstraction
type Storage interface {
    Save(data interface{}) error
    Find(id string) (interface{}, error)
}
Enter fullscreen mode Exit fullscreen mode
  1. Logging
type Logger interface {
    Info(msg string)
    Error(msg string)
}
Enter fullscreen mode Exit fullscreen mode

Interfaces are one of Go's most powerful features for writing flexible, testable code. Start small, focus on behavior, and let interfaces emerge from your code naturally.

Baamaapii

Top comments (0)