Background:
Go has implemented a simple yet powerful concept of methods and interfaces based on duck typing. Methods can only be attached to named types (struct or alias), and interfaces are a set of methods. This is key to polymorphism and abstractions without the need for explicit implements declaration.
Problem:
Programmers coming from Java or C# often expect explicit keywords implements or extends and get confused by the differences between methods with value receivers vs pointer receivers, leading to unpredictable behavior and errors when implementing interfaces.
Solution:
Definition of a method and interface:
type User struct { Name string } func (u User) Greet() string { return "Hello, " + u.Name } func (u *User) SetName(name string) { u.Name = name } type Greeter interface { Greet() string }
Key Features:
Can you declare methods for an alias type with a base type of int or string?
Yes, if it is a named type, for example:
type MyInt int func (m MyInt) Double() int { return int(m) * 2 }
What is the difference between implementing an interface through pointer and value methods?
If the interface method is declared as (T), both T and *T implement the interface. If (*T), only *T satisfies the interface. This is critical for passing structures to functions that accept interfaces.
How does "zero value" for interface work and what happens if a method is called on a nil value?
An uninitialized interface variable is nil; attempting to call a method on a nil field will panic if there is no explicit nil-pointer handling implemented.
A type declared with pointer methods (*T) while the interface expects value methods (T) causes the struct not to compile when trying to use it in interfaces. Attempting to declare a method for a []User type variable instead of a User type.
Pros:
Cons:
All methods implementing interfaces are declared with the correct receiver. Interfaces are not used where they are not needed (concrete type where possible, polymorphism where necessary).
Pros:
Cons: