Go

Why does Go favour small interfaces? Give examples of composition.

Question 96MediumGo 1.22 to 1.25

"The bigger the interface, the weaker the abstraction" (Rob Pike). A one-method interface is easy to satisfy, so many types implement it, and it composes well. io.Reader is implemented by files, sockets, gzip streams, HTTP bodies, strings.Reader and more. Every function that accepts an io.Reader works with all of them.

// Compose behaviour by wrapping small interfaces
func CountLines(r io.Reader) (int, error) {
    sc := bufio.NewScanner(r)
    n := 0
    for sc.Scan() {
        n++
    }
    return n, sc.Err()
}

f, _ := os.Open("log.gz")
defer f.Close()
gz, _ := gzip.NewReader(f)                 // io.Reader wrapping io.Reader
limited := io.LimitReader(gz, 10<<20)      // cap at 10 MiB
tee := io.TeeReader(limited, sha256.New()) // hash while reading
n, err := CountLines(tee)

Common single-method interfaces: io.Reader, io.Writer, io.Closer, fmt.Stringer, error, http.Handler, sort.Interface (three methods), context.Context (four methods), and encoding.TextMarshaler.

By convention, a one-method interface is named after its method plus "-er" (Reader, Flusher). Larger contracts are built by embedding small interfaces (io.ReadWriteCloser) rather than by declaring one large interface.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions