PY
GO

Python to Go

10 lessons

Progress0%
1Variables & Types2Functions3Lists → Slices, Dicts → Maps4Classes → Structs5asyncio → Goroutines6Modules → Packages7Interfaces8Error Handling Patterns9Testing10Standard Library
All Mirror Courses
PY
GO
Interfaces
MirrorLesson 7 of 10
Lesson 7

Interfaces

Go structural typing vs Python duck typing — explicit vs implicit

Introduction

In this lesson, you'll learn about interfaces in Go. Coming from Python, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
PY
From Python:

In Python, you're familiar with go structural typing vs python duck typing — explicit vs implicit.

GO
In Go:

Go has its own approach to go structural typing vs python duck typing — explicit vs implicit, which we'll explore step by step.

The Go Way

Let's see how Go handles this concept. Here's a typical example:

GO
Go Example
package main

import "fmt"

// Interface — structural like Python Protocol
type Animal interface {
    Speak() string
    Move()  string
}

// No "implements" keyword — satisfy implicitly
type Dog struct{ Name string }
func (d Dog) Speak() string { return "Woof" }
func (d Dog) Move()  string { return "runs" }

type Robot struct{}
func (r Robot) Speak() string { return "Beep" }
func (r Robot) Move()  string { return "rolls" }

func MakeNoise(a Animal) {
    fmt.Println(a.Speak())
}

// Interface composition
type Stringer interface { String() string }
type Named   interface { Name() string }
type NamedStringer interface { Stringer; Named }

// Empty interface — any type
func PrintAny(v any) { fmt.Println(v) }

// Type assertion
func TypeCheck(v any) {
    if s, ok := v.(string); ok {
        fmt.Println("string:", s)
    }
}

func main() {
    MakeNoise(Dog{"Rex"})  // Woof
    MakeNoise(Robot{})     // Beep
}

Comparing to Python

Here's how you might have written similar code in Python:

PY
Python (What you know)
from typing import Protocol

# Protocol: structural typing (Python 3.8+)
class Animal(Protocol):
    def speak(self) -> str: ...
    def move(self) -> str: ...

# Any class with these methods satisfies Animal
class Dog:
    def speak(self) -> str: return "Woof"
    def move(self) -> str: return "runs"

class Robot:
    def speak(self) -> str: return "Beep"
    def move(self) -> str: return "rolls"

def make_noise(a: Animal) -> None:
    print(a.speak())

# Works at runtime without explicit declaration
make_noise(Dog())   # Woof
make_noise(Robot()) # Beep

# Abstract base class (nominal typing)
from abc import ABC, abstractmethod
class Shape(ABC):
    @abstractmethod
    def area(self) -> float: ...
Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

GO
In Go:

Both Go and Python use structural typing — no explicit 'implements' needed

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

GO
In Go:

Go interfaces are compile-time checked; Python duck typing is checked at runtime

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

GO
In Go:

Python Protocol requires importing and declaring; Go interface is just a type declaration

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

GO
In Go:

Go interface composition (embedding) vs Python multiple Protocol inheritance

Mirror Card
PY
From Python:

You may be used to different syntax or behavior.

GO
In Go:

'any' in Go = interface{} = Python's Any type hint

Step-by-Step Breakdown

1. Implicit Satisfaction

Like Python duck typing, Go satisfies interfaces automatically. Unlike Python, Go checks this at compile time.

PY
Python
class Dog:
    def speak(self): return "Woof"
# Implicitly satisfies Animal Protocol
GO
Go
type Sayer interface { Say() string }
type Dog struct{}
func (d Dog) Say() string { return "Woof" }
// Dog implicitly implements Sayer — compile-time checked

2. Interface Composition

Embed interfaces to compose larger ones. This is more common in Go than Python's Protocol inheritance.

PY
Python
class Combined(Protocol):
    def read(self) -> str: ...
    def write(self, s: str) -> None: ...
GO
Go
type Reader interface { Read(p []byte) (int, error) }
type Writer interface { Write(p []byte) (int, error) }
type ReadWriter interface { Reader; Writer } // compose

3. Type Assertions

Use type assertions to extract the concrete type from an interface. Always use the two-value form to avoid panics.

PY
Python
if isinstance(v, str):
    print(v.upper())
GO
Go
if s, ok := v.(string); ok {
    fmt.Println(strings.ToUpper(s))
}
// Type switch
switch t := v.(type) {
case string:  fmt.Println("str:", t)
case int:     fmt.Println("int:", t)
default:      fmt.Println("other")
}

4. io.Reader / io.Writer Pattern

Go's stdlib defines small, composable interfaces like io.Reader and io.Writer. Code that accepts these works with files, network connections, buffers, etc.

PY
Python
from typing import IO
def process(f: IO[str]) -> str:
    return f.read()
GO
Go
import "io"
func Process(r io.Reader) ([]byte, error) {
    return io.ReadAll(r)
}
// Works with: os.File, bytes.Buffer, net.Conn, strings.Reader
Rule of Thumb
Accept interface types (io.Reader) in function parameters, not concrete types (os.File).

Common Mistakes

When coming from Python, developers often make these mistakes:

  • Both Go and Python use structural typing — no explicit 'implements' needed
  • Go interfaces are compile-time checked; Python duck typing is checked at runtime
  • Python Protocol requires importing and declaring; Go interface is just a type declaration
Common Pitfall
Don't assume Go works exactly like Python. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • Go interfaces are satisfied implicitly — like Python Protocol, but compile-time checked
  • Compose interfaces by embedding: type RW interface { Reader; Writer }
  • Type assertion: v.(Type) — use two-value form (v, ok) to avoid panic
  • io.Reader/Writer are the fundamental Go interfaces — accept them instead of concrete file types
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your Python code in Go to practice these concepts.
PreviousNext