Methods in Go
In this tutorial, we are going to discuss about methods in Go language.
Go methods are similar to Go function with one difference, i.e, the method contains a receiver argument in it. With the help of the receiver argument, the method can access the properties of the receiver.
The receiver argument has a name and a type. It appears between the func
keyword and the method name.
func (receiver Type) MethodName(parameterList) (returnTypes) { }
The receiver can be of struct type or non-struct type. When you create a method in your code the receiver and receiver type must present in the same package.
You are not allowed to create a method in which the receiver type is already defined in another package including inbuilt type like int, string, etc. If you try to do so, then the compiler will give an error.
package main
import (
"fmt"
)
type Employee struct {
name string
age int
salary int
}
/*
displayDetails() method has Employee as the receiver type
*/
func (e Employee) displayDetails() {
fmt.Println("Name : ", e.name)
fmt.Println("Salary : ", e.salary)
fmt.Println("Age : ", e.age)
}
func main() {
emp := Employee{
name: "Ashok Kumar",
salary: 50000,
age: 29,
}
emp.displayDetails()
}
Output
Name : Ashok Kumar
Salary : 50000
Age : 29
In Go language, you are allowed to create a method with non-struct type receiver as long as the type and the method definitions are present in the same package.
If they present in different packages like int, string, etc, then the compiler will give an error because they are defined in different packages.
package main
import "fmt"
type data int
func (d1 data) multiply(d2 data) data {
return d1 * d2
}
/*
// if you try to run this code, then compiler will throw an error
func (d1 int) multiply(d2 int) int {
return d1 * d2
}
*/
func main() {
value1 := data(10)
value2 := data(20)
res := value1.multiply(value2)
fmt.Println("Final result : ", res)
}
Output
Final result : 200
Methods vs Functions
The above struct type program can be rewritten using only functions and without methods.
package main
import (
"fmt"
)
type Employee struct {
name string
age int
salary int
}
/*
displayDetails() method converted to function with Employee as parameter
*/
func displayDetails(e Employee) {
fmt.Println("Name : ", e.name)
fmt.Println("Salary : ", e.salary)
fmt.Println("Age : ", e.age)
}
func main() {
emp := Employee{
name: "Ashok Kumar",
salary: 50000,
age: 29,
}
displayDetails(emp)
}
Output
Name : Ashok Kumar
Salary : 50000
Age : 29
In the program above, the displayDetails
method is converted to a function and the Employee
struct is passed as a parameter to it. This program also produces the exact same output.
So why do we have methods when we can write the same program using functions. There are a couple of reasons for this. Let’s look at them one by one.
1. Go is not a pure object-oriented programming language and it does not support classes. Methods help you write object-oriented style code in Go. Method calls are much easier to read and understand than function calls.
2. Methods with the same name can be defined on different types whereas functions with the same names are not allowed. Let’s assume that we have a Square
and Circle
structure. It’s possible to define a method named Area
on both Square
and Circle
. This is done in the program below.
package main
import (
"fmt"
"math"
)
type Rectangle struct {
length int
width int
}
type Circle struct {
radius float64
}
func (r Rectangle) Area() int {
return r.length * r.width
}
func (c Circle) Area() float64 {
return math.Pi * c.radius * c.radius
}
func main() {
r := Rectangle{
length: 10,
width: 5,
}
fmt.Println("Area of rectangle : ", r.Area())
c := Circle{
radius: 12,
}
fmt.Println("Area of circle : ", c.Area())
}
Output
Area of rectangle : 50
Area of circle : 452.3893421169302
Difference Between Method and Function

Methods with Pointer receivers
All the examples that we saw in the previous sections had a value receiver.
With a value receiver, the method operates on a copy of the value passed to it. Therefore, any modifications done to the receiver inside the method is not visible to the caller.
// Method with pointer receiver
func (receiver *Type) MethodName(parameterList) (returnTypes) {
}
Methods with pointer receivers can modify the value to which the receiver points. Such modifications are visible to the caller of the method as well.
package main
import (
"fmt"
)
type Employee struct {
name string
age int
}
func (e Employee) changeName(newName string) {
e.name = newName
}
func (e *Employee) changeAge(newAge int) {
e.age = newAge
}
func main() {
e := Employee{
name: "Ashok Kumar",
age: 28,
}
fmt.Println("Employee name before change : ", e.name)
e.changeName("Ashok")
fmt.Println("Employee name after change : ", e.name)
fmt.Println("Employee age before change : ", e.age)
e.changeAge(29)
fmt.Println("Employee age after change : ", e.age)
}
Output
Employee name before change : Ashok Kumar
Employee name after change : Ashok Kumar
Employee age before change : 28
Employee age after change : 29
Method definition restrictions
Note that, For you to be able to define a method on a receiver, the receiver type must be defined in the same package.
Go doesnβt allow you to define a method on a receiver type that is defined in some other package (this includes built-in types such as int
as well).
In all the previous examples, the structs and the methods were defined in the same package main
. Therefore, they worked. However, if you try to define a method on a type defined in some other package, the compiler will complain.