Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Go Design Patterns

You're reading from   Go Design Patterns Best practices in software development and CSP

Arrow left icon
Product type Paperback
Published in Feb 2017
Publisher Packt
ISBN-13 9781786466204
Length 402 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Mario Castro Contreras Mario Castro Contreras
Author Profile Icon Mario Castro Contreras
Mario Castro Contreras
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Ready... Steady... Go! FREE CHAPTER 2. Creational Patterns - Singleton, Builder, Factory, Prototype, and Abstract Factory Design Patterns 3. Structural Patterns - Composite, Adapter, and Bridge Design Patterns 4. Structural Patterns - Proxy, Facade, Decorator, and Flyweight Design Patterns 5. Behavioral Patterns - Strategy, Chain of Responsibility, and Command Design Patterns 6. Behavioral Patterns - Template, Memento, and Interpreter Design Patterns 7. Behavioral Patterns - Visitor, State, Mediator, and Observer Design Patterns 8. Introduction to Gos Concurrency 9. Concurrency Patterns - Barrier, Future, and Pipeline Design Patterns 10. Concurrency Patterns - Workers Pool and Publish/Subscriber Design Patterns

Pointers and structures

Pointers are the number one source of a headache of every C or C++ programmer. But they are one of the main tools to achieve high-performance code in non-garbage-collected languages. Fortunately for us, Go's pointers have achieved the best of both worlds by providing high-performance pointers with garbage-collector capabilities and easiness.

On the other side for its detractors, Go lacks inheritance in favor of composition. Instead of talking about the objects that are in Go, your objects have other . So, instead of having a car structure that inherits the class vehicle (a car is a vehicle), you could have a vehicle structure that contains a car structure within.

What is a pointer? Why are they good?

Pointers are hated, loved, and very useful at the same time. To understand what a pointer is can be difficult so let's try with a real world explanation. As we mentioned earlier in this chapter, a pointer is a like a mailbox. Imagine a bunch of mailboxes in a building; all of them have the same size and shape but each refers to a different house within the building. Just because all mailboxes are the same size does not mean that each house will have the same size. We could even have a couple of houses joined, a house that was there but now has a license of commerce, or a house that is completely empty. So the pointers are the mailboxes, all of them of the same size and that refer to a house. The building is our memory and the houses are the types our pointers refer to and the memory they allocate. If you want to receive something in your house, it's far easier to simply send the address of your house (to send the pointer) instead of sending the entire house so that your package is deposited inside. But they have some drawbacks as if you send your address and your house (variable it refers to) disappears after sending, or its type owner change--you'll be in trouble.

How is this useful? Imagine that somehow you have 4 GB of data in a variable and you need to pass it to a different function. Without a pointer, the entire variable is cloned to the scope of the function that is going to use it. So, you'll have 8 GB of memory occupied by using this variable twice that, hopefully, the second function isn't going to use in a different function again to raise this number even more.

You could use a pointer to pass a very small reference to this chunk to the first function so that just the small reference is cloned and you can keep your memory usage low.

While this isn't the most academic nor exact explanation, it gives a good view of what a pointer is without explaining what a stack or a heap is or how they work in x86 architectures.

Pointers in Go are very limited compared with C or C++ pointers. You can't use pointer arithmetic nor can you create a pointer to reference an exact position in the stack.

Pointers in Go can be declared like this:

number := 5 

Here number := 5 code represents our 4 GB variable and pointer_to_number contains the reference (represented by an ampersand) to this variable. It's the direction to the variable (the one that you put in the mailbox of this house/type/variable). Let's print the variable pointer_to_number , which is a simple variable:

println(pointer_to_number) 
0x005651FA 

What's that number? Well, the direction to our variable in memory. And how can I print the actual value of the house? Well, with an asterisk (*) we tell the compiler to take the value that the pointer is referencing, which is our 4 GB variable.

 println(*pointer_to_number) 
5 

Structs

A struct is an object in Go. It has some similarities with classes in OOP as they have fields. Structs can implement interfaces and declare methods. But, for example, in Go, there's not inheritance. Lack of inheritance looks limiting but in fact, composition over inheritance was a requirement of the language.

To declare a structure, you have to prefix its name with the keyword type and suffix with the keyword struct and then you declare any field or method between brackets, for example:

type Person struct { 
    Name string 
    Surname string 
    Hobbies []string 
    id string 
} 

In this piece of code, we have declared a Person structure with three public fields (Name, Age , and Hobbies) and one private field (id, if you recall the Visibility section in this chapter, lowercase fields in Go refers to private fields are just visible within the same package). With this struct, we can now create as many instances of Person as we want. Now we will write a function called GetFullName that will give the composition of the name and the surname of the struct it belongs to:

func (person *Person) GetFullName() string { 
    return fmt.Sprintf("%s %s", person.Name, person.Surname) 
} 
 
func main() { 
    p := Person{ 
        Name: "Mario", 
        Surname: "Castro", 
        Hobbies: []string{"cycling", "electronics", "planes"}, 
        id: "sa3-223-asd", 
    } 
 
    fmt.Printf("%s likes %s, %s and %s\n", p.GetFullName(), p.Hobbies[0], p.Hobbies[1], p.Hobbies[2]) 
} 

Methods are defined similarly to functions but in a slightly different way. There is a(p *Person) that refers to a pointer to the created instance of the struct (recall the Pointers section in this chapter). It's like using the keyword this in Java or self in Python when referring to the pointing object.

Maybe you are thinking why does (p *Person) have the pointer operator to reflect that p is actually a pointer and not a value? This is because you can also pass Person by value by removing the pointer signature, in which case a copy of the value of Person is passed to the function. This has some implications, for example, any change that you make in p if you pass it by value won't be reflected in source p. But what about our GetFullName() method?

func (person Person) GetFullName() string { 
    return fmt.Sprintf("%s %s", person.Name, person.Surname) 
} 

Its console output has no effect in appearance but a full copy was passed before evaluating the function. But if we modify person here, the source p won't be affected and the new person value will be available only on the scope of this function.

On the main function, we create an instance of our structure called p. As you can see, we have used implicit notation to create the variable (the := symbol). To set the fields, you have to refer to the name of the field, colon, the value, and the comma (don't forget the comma at the end!). To access the fields of the instantiated structure, we just refer to them by their name like p.Name or p.Surname. You use the same syntax to access the methods of the structure like p.GetFullName().

The output of this program is:

$ go run main.go 
Mario Castro likes cycling, electronics and planes

Structures can also contain another structure (composition) and implement interface methods apart from their own but, what's an interface method?

You have been reading a chapter from
Go Design Patterns
Published in: Feb 2017
Publisher: Packt
ISBN-13: 9781786466204
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime