Contents
Outline
In this blog post, I will introduce what the Interface
is and how to use the interface in Golang. You can see the full source code of this blog post on the link below.
Interface
In Golang, the interface is an abstract interaction, not a concrete object, and is used to show relationships.
You can define the interface in Golang like the below.
type INTERFACE_NAME interface {
METHOD_NAME(PARAMETER_NAME) RETURN_TYPE
...
}
In Golang, you can use the type
keyword and add the interface
keyword after the interface name to define the interface.
In the interface, you can define the methods that are not implemented (only method names, parameters, and return types), and we’ll recognize the types with these declared methods as the interface we defined.
In Golang, the interface is one of the types, and you can make variables with the interface.
To check this, create the main.go
file and modify it like the below.
package main
import "fmt"
type SampleInterface interface {
SampleMethod()
}
func main() {
var s SampleInterface
fmt.Println(s)
}
When you execute the code, you can see the following result.
# go run main.go
<nil>
The interface is used for abstraction that hides internal behavior and is mainly used for decoupling that eliminates dependence through abstraction.
Interface default value
In Golang, the interface default value is nil
. To check this, modify the main.go
file like the below.
package main
import "fmt"
type SampleInterface interface {
SampleMethod()
}
func main() {
var s SampleInterface
fmt.Println(s)
s.SampleMethod()
}
After writing the code, execute the command below to make a module.
go mod init github.com/dev-yakuza/study-golang/interface/nil
go mod tidy
go build
When you execute the command, you can see the file named nil
same location as the main.go
file.
When you execute the file, you can see the following result.
# ./nil
<nil>
panic: runtime error: invalid memory address or nil pointer dereference
There is no grammatical error in the example above. However, the interface value is not assigned so the runtime error(nil pointer error) occurs.
If you want to know more details about the Module in Golang, see the following link.
Interface rule
There are some rules for the interface in Golang.
- Methods should have the method name.
- Even if the parameters are different, the same name methods can’t exist.
- Methods in the interface doesn’t include the implements
type SampleInterface interface {
String() string
String(a int) string // Error: duplicated method name
_(x int) int // Error: no name method
}
To check this, modify the main.go
file like the below.
package main
import "fmt"
type SampleInterface interface {
String() string
String(a int) string // Error: duplicated method name
_(x int) int // Error: no name method
}
func main() {
var s SampleInterface
fmt.Println(s)
}
When the code is executed, you can see the following result.
# go run main.go
# command-line-arguments
./main.go:7:2: duplicate method String
./main.go:8:2: methods must have a unique non-blank name
Example
Let’s make a simple example to understand the interface in Golang. First, create the main.go
file and modify it like the below.
package main
import "fmt"
type Human interface {
Walk() string
}
type Student struct {
Name string
Age int
}
func (s Student) Walk() string {
return fmt.Sprintf("%s can walk", s.Name)
}
func (s Student) GetAge() int {
return s.Age
}
func main() {
s := Student{Name: "John", Age: 20}
var h Human
h = s
fmt.Println(h.Walk())
// fmt.Println(h.GetAge()) // ERROR
}
When you execute the code, you can see the following result.
# go run main.go
John can walk
Let’s see the details of the code. There is the Human
interface and the interface has the Walk
function.
type Human interface {
Walk() string
}
And the Student
struct type has the Name
and Age
variables, and it has the Walk
and GetAge
methods.
type Student struct {
Name string
Age int
}
func (s Student) Walk() string {
return fmt.Sprintf("%s can walk", s.Name)
}
func (s Student) GetAge() int {
return s.Age
}
Next, the variable is created with the Student
struct, and is assigned to the Human
interface.
func main() {
s := Student{Name: "John", Age: 20}
var h Human
h = s
fmt.Println(h.Walk())
// fmt.Println(h.GetAge()) // ERROR
}
The variabe that is assgined to Human
has Walk
function, so the Walk
function in the Human
variable can be called, but the GetAge
function can’t be called.
Dock typing
You can impelement Duck typing with the interface in Golang. Duck typing means that if you see a bird and it walks like a duck, flies like a duck, and makes a sound like a duck, the bird will be called a duck.
In other words, regardless of what variables and functions are in the object, you can call the object as your interface that you want to define.
Let’s see an example to understand it. First, make the user/main.go
file and modify it like the below.
package user
import "fmt"
type User struct {
Name string
}
func (u User) Walk() {
fmt.Println("Walking")
}
func (u User) Talk() {
fmt.Println("Talking")
}
And then, execute the command below to make a module.
# cd user
go mod init github.com/dev-yakuza/study-golang/interface/user
go mod tidy
This user
package has the User
type, and the User
type has the Walk
and Talk
methods. Next, let’s do Duck typing with the user
package via the interface.
To do Duck typing, create the main/main.go
file in the same directory as the user
folder and modify it like the below.
package main
import (
"fmt"
"github.com/dev-yakuza/study-golang/interface/user"
)
type Human interface {
Walk()
Talk()
}
func main() {
u := user.User{Name: "John"}
fmt.Println(u)
h := Human(u)
fmt.Println(h)
}
And then, execute the command below to make a module and connect the local module.
go mod init github.com/dev-yakuza/study-golang/interface/main
go mod edit -replace github.com/dev-yakuza/study-golang/interface/user=../user
go mod tidy
When you execute the module, you can see the following result.
# go run main.go
{John}
{John}
As you see the main/main.go
, the User
type is replaced with the Human
interface. We don’t care about the variables and methods of the User
type. Just, if the type has Walk
and Talk
methods, it can be called as Human
interface in the main
package.
Like this, when you use the external packages, the interface can change the object to suit your code and ust it. Of course, when you create the external package, you don’t need to think about the interface. You just implement the variable and methods on your side. So, sometimes, the type in the external package doesn’t implement the methods that you defined in the interface. At this time, the compile error occurs.
Duck typing enables coding centered on users who use the code. The external package providers provide the concrete object, and the programmers who use the external package define the interface and use the object by their own type.
Embedded interface
In Golang, the interface can be embedded in other interfaces. This is called the Embedded interface
in Golang.
type Reader interface {
Read() (n int, err error)
Close() error
}
type Writer interface {
Write() (n int, err error)
Close() error
}
type ReadWriter interface {
Reader
Writer
}
The ReadWriter
interface includes the Reader
and Writer
interface, and has the Read
, Write
and Close
methods.
Convert type
In Golang, you can convert the interface to the concrete type like the below.
var a Interface
t := a.(ConcreteType)
To convert the interface to the type, you can use .(type)
. When you use the code like above, a ConcreteType
variable is created and assigned to the t
variable.
You can convert the interface to the same inteface type, but if variables or methods that the type doesn’t have are called, the runtime error occurs.
To check this, create the main.go
file and modify it like the below.
package main
import "fmt"
type Human interface {
Learn()
}
type Teacher struct {
Name string
}
func (m *Teacher) Learn() {
fmt.Println("Teacher can learn")
}
func (m *Teacher) Teach() {
fmt.Println("Teacher can teach")
}
type Student struct {
Name string
}
func (m *Student) Learn() {
fmt.Println("Student can learn")
}
func Study(h Human) {
if h != nil {
h.Learn()
var s *Student
s = h.(*Student)
fmt.Printf("Name: %v\n", s.Name)
// s.Teach() // ERROR
}
}
func main() {
Study(&Student{Name: "John"})
}
When the code is executed, the following result is shown.
# go run main.go
Student can learn
Name: John
WHen you convert the intefacec, if the type is not the corresponding interface type, the compile error occurs. To check this, modify the main.go
file like the below.
package main
import "fmt"
type Stringer interface {
String() string
}
type Student struct {
}
func main() {
var stringer Stringer
s := stringer.(*Student)
fmt.Println(s)
}
When you execute the code, you can see the following result.
# go run main.go
# command-line-arguments
./main.go:14:15: impossible type assertion:
*Student does not implement Stringer (missing String method)
Convert different interface
In Golang, you can convert to different interface types. There is no problem with grammar at all, but when you actually run it and there is no corresponding method, the runtime error occurs.
To check this, create the main.go
file and modify it like the below.
package main
import "fmt"
type Teacher interface {
Teach()
}
type Student interface {
Learn()
}
type Person struct {
}
func (f *Person) Learn() {
fmt.Println("Person can learn")
}
func Teach(s Student) {
t := s.(Teacher)
t.Teach()
}
func main() {
p := &Person{}
Teach(p)
}
When you execute the code, you can see the following result.
# go run main.go
panic: interface conversion: *main.Person is not main.Teacher: missing method Teach
After receiving the variable of the Person
type as the Student
interface and converting the assigned Student
interface to the Teacher
interface, the Teach
method of the Teacher
interface is called. There is no grammar problem, so there is no compile error. However, when the code is actually executed, the runtime error occurs because there is no Teach
method in the Person
type.
To prevent this issue, Golang provides a feature to check whether the type conversion is successful.
How to check type conversion succeeded
Converting between the interfaces is not a grammer problem. So, there is no compile error when you build the code. However, there is a possibility of an runtime error. To prevent the runtime error, we can check the type conversion succeeded in Golang.
var a Interface
t, ok := a.(ConcreteType)
- t: the result of the type conversion
- ok: the result of the type conversion succeeded or not
To check this, modify the main.go
file like the below.
package main
import "fmt"
type Teacher interface {
Teach()
}
type Student interface {
Learn()
}
type Person struct {
}
func (f *Person) Learn() {
fmt.Println("Person can learn")
}
func main() {
p := &Person{}
s := Student(p)
s.Learn()
t, ok := s.(Teacher)
fmt.Println(ok)
if ok {
t.Teach()
}
}
When you execute the code, you can see the following result.
# go run main.go
Person can learn
false
The Person
type can be converted to the Student
interface, but the Student
interface doesn’t have the Teach
method, so it can’t be converted to the Teacher
interface.
So, when you try to convert the interface, you can see the result is false
.
Like this, you can check the type conversion succeeded or not. And when converting the interface, it is mainly used as follows.
if t, ok := s.(Teacher); ok {
t.Teach()
}
Empty interface
Sometime, the empty interface is used in Golang. The empty interface doesn’t have any methods, so any types can be assigned to it.
interface {}
This empty interface is used in the following cases.
package main
import "fmt"
type Student struct {
Age int
}
func Print(v interface{}) {
switch v := v.(type) {
case int:
fmt.Println("v is int", v)
case float64:
fmt.Println("v is float64", v)
case string:
fmt.Println("v is string", v)
default:
fmt.Printf("Not supported %T:%v", v, v)
}
}
func main() {
Print(10)
Print(3.14)
Print("Hello word")
Print(Student{Age: 10})
}
When the code is executed, the following result is shown.
# go run main.go
v is int 10
v is float64 3.14
v is string Hello word
Not supported main.Student:{10}%
Completed
Done! we’ve seen what the interface is and how to use the interface in Golang. Also, we’ve learned Duck typing and how to convert the inteface to the concrete type or the different interface.
Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!
App promotion
Deku
.Deku
created the applications with Flutter.If you have interested, please try to download them for free.