top of page
  • khangaonkar

Go Tutorial: Receivers

When I was new to the Go programming language and saw this syntax

func (m *Service) addNumbers(a int32, b int32) int32

I was confused. I had not seen syntax like (m *Service) between func and the function name in any other language. This is a receiver and if you are new to Go, this is likely to be a new concept you have not seen earlier. The purpose of this blog is to explain Go receivers.


Any one who has done programming knows what a function is. A function is a reusable block of code that does a specific task. We write functions so that code is modular and can be reused.


func addNumbers(a int32, b int32) int32 {
	return a + b
}

This was how code is written in procedural languages.


Then came along object oriented language like C++ and Java. Here data and code was encapsulated into classes. Each class has member variable (data) and methods (functions) that could operated on the data. In Java, you would have class and method as below

public class MyNumber {
  private int first;
  private int second;

  // method
  public int sum() { 
     return first + second;
  }
}

Go does not have the concept of classes. Go has struct which is a collection of fields.


type struct MyNumbers {
	first int32
    second int32
}

A struct is just data. Unlike classes you cannot add methods to it.


Go receivers


In Go, you associate a function with struct by adding a receiver to it. In the code below, we defined a struct MyNumbers. We associated a function sum with struct by adding a receiver (m MyNumbers) between func and the function name sum().


When you add a receiver to a function, it becomes a method. sum is now a method in Go.


type MyNumbers struct {
	first  int32
	second int32
}

func (m MyNumbers) sum() int32 {
	return m.first + m.second
}

func main() {
	d := MyNumbers{3, 4}
	fmt.Println(d.sum())
}
// will print 7

In the example above, the receiver is a value receiver, meaning the method cannot modify the original.


Pointer receivers

A method can have a pointer receiver. The difference with a pointer receiver is that the method can modify the value of the receiver.

type MyNumbers struct {
	first  int32
	second int32
}

func (m *MyNumbers) increment() {
	m.first++
	m.second++
}

func main() {
	d := MyNumbers{3, 4}
	d.increment()
	fmt.Println(d.first, d.second)
}
// 4 5

Note that even though increment has a pointer receiver, it can still be called on d which is a value and not a pointer. (Go weirdness). Calling sum ( which has a value receiver) on a pointer to MyNumbers also works.


e := &MyNumbers{7, 8}
fmt.Println(e.sum())
// 15

Receivers on non-structs


You can also add methods to on non structs. However the type needs to be declared locally. So you cannot directly add a method to int. You need a local type that aliases int. This is a definite plus compared to other languages.


type Myint int

func (m Myint) square() int {
	return int(m) * int(m)
}

// func (m int) square() int {} will give compiler error

func main() {
	myint := Myint(4)
	fmt.Println(myint.square())
   // 16
}

Other notes

Methods can be overloaded. Functions cannot be overloaded.


Functions can be passed around as a parameter. Methods cannot be passed around as a parameter.


Summary


In conclusion, use a receiver to associate functions with types and in the process create go methods. Receivers can be values or pointers. With pointer receivers, the method can modify the value pointed to. Another advantage of pointer is that with value receiver, the value is copied on each invocation. For larger structs you definitely want to use a pointer. But for simpler cases, using a value is much easier.


Why does the language need receivers ? Without receivers, you would need to pass the type as parameter as in procedural languages. A receiver is in some ways just a special type of parameter. Some might say syntactic sugar for parameters.


Even though Go is not object oriented language, this makes it like one. Some might say - it is neither here nor there. My opinion is that even being object oriented like, makes programming easier. One can argue that the Go way of associating functions to data is simpler that all the syntax that is involved in declaring a Java class. But it is more a matter of taste.


The value of receivers will more evident when we talk of interfaces, which will the topic of a future blog.






Recent Posts

See All

JDK22: New features in Java 22

JDK 22 was released on March 19, 2024. As always, a new suite of goodies is made available for the benefit of the Java programmer. Many of them are in preview. This is a very brief listing of the new

Go review: Should I use the Go programming language ?

Overview Go was developed by engineers at Google. Their primary motivation was dislike for C++. Goal was to create a language for systems programming. Its popularity has been slowly but steadily incre

Comentarios


bottom of page