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. Let’s explore how to use them effectively and avoid common pitfalls.

What Makes Go Interfaces Special? (2 minutes)

Unlike other languages, Go interfaces are:

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

Basic Interface Usage (5 minutes)

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 ```go // 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 }




2. **Accept Interfaces, Return Structs**


```go
// 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

Wrapping Up

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.

What’s your favorite use of interfaces in Go? Have you discovered any interesting patterns? Share in the comments!

Baamaapii 👋

Top comments (0)