Mahdi.Kh
September 21, 2026
We get familiar with the concept of interfaces and learn how to use interfaces in the Go language.
An interface in programming is a contract or template that specifies which methods a type must implement, without specifying any implementation details.
An interface essentially describes the behavior or capabilities an object should have.
In Go, interfaces are a data type that only defines methods' signatures and has no implementation.
In Go, implementing interfaces is done implicitly, meaning that if a type has all the methods defined in an interface, it has implemented that interface.
In the example below, File automatically implements Writer, because it has all of its methods:
Type assertion, or interface assertion, is a mechanism that lets a developer extract the concrete type of a value that has an interface type.
The general syntax of a type assertion is as follows:
i is a value of type interface.
T is the type we expect the value i to actually be.
value is the variable that the extracted value of type T is stored in.
If the value i is actually of type T, the operation succeeds. Otherwise, the program will panic at runtime (a runtime panic).
To avoid a panic and safely check the value's type, you can use the second form of type assertion:
If the value i is of type T, the variable ok will be true.
Otherwise, ok will be , and will hold the zero value of type .
falsevalueTIn Go, this pattern is known as the comma-ok idiom, and it's a common way to do a type assertion safely.
Now let's look at some real examples:
Also, if you've created your own custom interface, you can do the same thing:
In the example above, we used type assertion inside the DescribeShape function.
Type assertion is also useful for checking whether a value implements a specific interface. In this approach, we need to declare our variable as an interface type, or convert it to type interface using a type conversion, then put the value we want into that variable, and finally use a type assertion to check whether that data type implements the interface we want. Take a look at the example below:
To check the actual type of a value that has an interface type, besides type assertion, you can use a type switch.
The empty interface, interface{}, means "any type." Because it has no methods, every type in Go implements it by default.
The empty interface can hold any kind of data, so wherever you need to be able to accept any kind of data, you can use the empty interface.
In Go 1.18, the any type was added to the language, and it's really just an alias for interface{}, but it makes code look more readable.
any is like a nicer name for interface{} that makes the code more readable.
The empty interface, interface{}, is a form of type erasure, meaning the actual type is hidden, and to use it again you need to use a type assertion or a type switch.
Using interface{} excessively or without good reason makes the code lose readability and type safety, because during development we need to check the older code to make sure what type of data was passed to the interface.
In Go, instead of inheritance, composition is used to build more complex structs and interfaces. This way, several interfaces can be combined to build a larger interface.
Suppose we have two separate interfaces:
Now we want to build a new interface that has both Read and Write:
Here, ReadWriter is a composition of Reader and Writer. Any type that implements both Reader and Writer has also implemented ReadWriter.
In Go, it's recommended that, instead of designing large interfaces, you design small interfaces with one or two methods and combine them through composition when needed. This is one of Go's well-known principles:
Design small interfaces. Compose them when needed
Previous part: The struct Data Type | Golang basics
Next part: Generics | Golang basics