Golang Methods Tutorial [Practical Examples]

Golang Methods Tutorial [Practical Examples]

Introduction to Golang Methods

Go methods are basically functions with receiver arguments between thefunckeyword and the name of the method. The receiver does appear in its own argument list. Go uses receivers to implement object orientation just like other languages do like python and Java where classes are used to achieve object orientation. Go does not have classes, but you can define methods on different types like struct, and non-struct types.

In Go and many other programming languages , methods are used to expose and hide properties of a type, and therefore with the help of receiver arguments , methods are used to hide and access the properties of a type.


Methods syntax

The unique thing about the above syntax is that the receiver type appears in its argument list. The receiver type declares the type the function is going to be attached to. One important thing to note is that the method and the receiver have to be in the same package. This means that Go does not allow us to declare a method and receiver whose type is defined in another package and this rule applies to built in types such as int andstring.

func (receiverName receiverType) methodName (parameter List)(returnTypes){
 <em>  method body</em>
}

The following figure highlights the different parts involved in defining a method. It shows the quart method attached to the type gallon based receiver via the g gallon receiver parameter:

image


Using Method with struct type receivers

In Go, you can define a method whose receiver is a struct or a non-struct type. For most of the examples in this article, structs will be used to demonstrate methods in Go. If you haven’t already, install Go runtime, and create a working directory and add main.go file in your working directory to start writing Go methods.

Example

package main

import "fmt"

type User struct {
   Name  string
   Email string
}

func (u User) userDetails() string {
   return fmt.Sprintf("User name is :%s and email is: %s", u.Name, u.Email)
}

func main() {
   user1 := User{Name: "John Doe", Email: "johndoe@golinuxcloud.com"}
   fmt.Println(user1.userDetails())
}

Explanation

In the preceding example, we have created aUserstruct, withNameandEmailattributes. We then define a method calleduserDetails(), with theUserstruct as the receiver indicated by (u User). In theuserDetails()method, we now have access to the receiver via theureceiver name. We use the dot notation to access the receiver attributes and methods like sou.Nameoru.Email. In the main function, we create an instance of theUserstruct, and print the details of the user on the screen by calling theuserDetails()method on theuser1instance.

Output

$ go run main.go
User name is :John Doe and email is: johndoe@golinuxcloud.com

Using Methods with non-struct receivers

In the preceding example, we defined methods with struct types. It is possible to define methods with other types that are not struct types. One important thing to note though is that when defining a method on a type, the definition of the receiver type and of the method should be in the same package.

Example

package main

import "fmt"

type myNumber int

func (num myNumber) square() myNumber {
   if num == 0 {
       return 1
   }
   return num * num
}

func main() {
   num := myNumber(25)
   sq := num.square()
   fmt.Printf("The square of %d is %d \n", num, sq)
}

Output

$ go run main.go
The square of 25 is 625

Using Methods with interface types

An interface in Go is a type with a defined method signature. Types with these methods defined in the interface implement the interface implicitly. With interfaces, the methods are defined both in the interface and the receiver as shown below.

Example

package main

import "fmt"

var URL string

type Protocal interface {
   request(URLEndpoint string)
   response() string
}
type HTTPProtocol struct {
   URL string
}

func (HTTP *HTTPProtocol) request(URLEndpoint string) {
   URL = fmt.Sprintf("%s/%s", HTTP.URL, URLEndpoint)
   HTTP.URL = URL
}
func (http HTTPProtocol) response() string {
   return URL
}
func main() {
   HTTPP := HTTPProtocol{URL: "https://www.golinuxcloud.com"}
   HTTPP.request("go-methods")
   res := HTTPP.response()
   fmt.Println(res)
   fmt.Println(HTTPP)
}

Explanation

In this example, we are trying to mimic request response client server architecture. We first declare aURLstring type at the top.Then we define aProtocolinterface with two methods namelyrequest()andresponse(). At this point, if we have a type with these methods defined, that type will implement ourProtocolinterface implicitly. Then we define aHTTPProtocolstruct type withrequest()andresponse()methods. Therequest()method has a pointer receiver, and that allows us to modify theURLattribute of theHTTPProtocolstruct. We also assign theURLstring type variable to the new URL. In the main function, we create an instance of theHTTPProtocolstruct (HTTPP) with a URL string. We then use therequest()method to pass the URL endpoint(“go-methods”), which goes ahead to effect the changes both on theURLvariable and theURLattribute of theHTTPProtocolinstance.

Output

$ go run main.go
https://www.golinuxcloud.com/methods
{https://www.golinuxcloud.com/methods}

Using Methods with value and pointer receivers

Go methods can accept both value and pointer receivers. In our previous example we used value receivers, in this section , we will work with both. A pointer in Go is a variable used to store the memory address of another variable, in this case we will use a pointer as a receiver. Go always passes by value , which means it creates a copy of the value in the function. If you call a method with a value receiver, and the method modifies that value, the caller will not see that modification made to the value. If you want to modify the value, the receiver has to be a pointer. In simple terms, we use pointer receivers in methods to modify the value the receiver points to and to avoid copying the value on each method call.

Learn more about pointers: Go Pointers Explained for Beginners [Practical Examples].

Example

package main

import "fmt"

type User struct {
   Name  string
   Email string
}

func (u User) userDetails() string {
   return fmt.Sprintf("User name is :%s and email is: %s", u.Name, u.Email)
}

func (u *User) changeDetails(newName, newEmail string) {
   u.Name = newName
   u.Email = newEmail
}

func main() {
   user1 := User{Name: "John Doe", Email: "johndoe@golinuxcloud.com"}
   fmt.Println(user1.userDetails())
   user1.changeDetails("Mary Doe", "marydoe@golinuxcloud.com")
   fmt.Println(user1.userDetails())
}

Explanation

In the above example, we add a new method calledchangeDetails()with a pointer receiver to the User struct type and anewNameof type string in the parameter list. We then use the dot notation to get access to the receiver’s name and email attribute and change it to thenewNameandnewEmailstring respectively. In the main function, we instantiate a new user(user1) with a name and an email. We then call thechangeDetails()function on theuser1instance , which modifies the name and email to whatever name and email we pass to thechangeDetails()method. When this code is executed, we notice that the name and email of theuser1changes to a new name and email courtesy of thechangeDetails()method.

Output

$ go run main.go
User name is :John Doe and email is: johndoe@golinuxcloud.com
User name is :Mary Doe and email is: marydoe@golinuxcloud.com

Summary

In this tutorial, we have learned about what methods are and what is the difference between a method and a function. We have also dived deep into the relationship between methods, receivers and interfaces. Go methods and interfaces are important features of Go that every Go developer should have at their fingertips.


References

Golang Methods
Go methods example

Antony Shikubu

Antony Shikubu

Systems Integration Engineer

Highly skilled software developer with expertise in Python, Golang, and AWS cloud services.