Search icon CANCEL
Subscription
0
Cart icon
Cart
Close icon
You have no products in your basket yet
Save more on your purchases!
Savings automatically calculated. No voucher code required
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Go Design Patterns

You're reading from  Go Design Patterns

Product type Book
Published in Feb 2017
Publisher Packt
ISBN-13 9781786466204
Pages 402 pages
Edition 1st Edition
Languages
Author (1):
Mario Castro Contreras Mario Castro Contreras
Profile icon Mario Castro Contreras
Toc

Table of Contents (17) Chapters close

Go Design Patterns
Credits
About the Author
About the Reviewer
www.PacktPub.com
Customer Feedback
Preface
1. Ready... Steady... Go! 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

Functions


A function is a small portion of code that surrounds some action you want to perform and returns one or more values (or nothing). They are the main tool for developer to maintain structure, encapsulation, and code readability but also allow an experienced programmer to develop proper unit tests against his or her functions.

Functions can be very simple or incredibly complex. Usually, you'll find that simpler functions are also easier to maintain, test and debug. There is also a very good advice in computer science world that says: A function must do just one thing, but it must do it damn well.

What does a function look like?

A function is a piece of code with its own variables and flow that doesn't affect anything outside of the opening and close brackets but global package or program variables. Functions in Go has the following composition:

func [function_name] (param1 type, param2 type...) (returned type1, returned type2...) { 
    //Function body 
} 

Following the previous definition, we could have the following example:

func hello(message string) error { 
    fmt.Printf("Hello %s\n", message) 
    return nil 
} 

Functions can call other functions. For example, in our previous hello function, we are receiving a message argument of type string and we are calling a different function fmt.Printf("Hello %s\n", message) with our argument as parameter. Functions can also be used as parameters when calling other functions or be returned.

It is very important to choose a good name for your function so that it is very clear what it is about without writing too many comments over it. This can look a bit trivial but choosing a good name is not so easy. A short name must show what the function does and let the reader imagine what error is it handling or if it's doing any kind of logging. Within your function, you want to do everything that a particular behavior need but also to control expected errors and wrapping them properly.

So, to write a function is more than simply throw a couple of lines that does what you need, that's why it is important to write a unit test, make them small and concise.

What is an anonymous function?

An anonymous function is a function without a name. This is useful when you want to return a function from another function that doesn't need a context or when you want to pass a function to a different function. For example, we will create a function that accepts one number and returns a function that accepts a second number that it adds it to the first one. The second function does not have a declarative name (as we have assigned it to a variable) that is why it is said to be anonymous:

func main(){ 
    add := func(m int){ 
         return m+1 
} 
 
    result := add(6) 
 
    //1 + 6 must print 7 
    println(result) 
} 

The add variable points to an anonymous function that adds one to the specified parameter. As you can see, it can be used only for the scope its parent function main and cannot be called from anywhere else.

Anonymous functions are really powerful tools that we will use extensively on design patterns.

Closures

Closures are something very similar to anonymous functions but even more powerful. The key difference between them is that an anonymous function has no context within itself and a closure has. Let's rewrite the previous example to add an arbitrary number instead of one:

func main(){ 
    addN := func(m int){ 
        return func(n int){ 
            return m+n 
        }            
    } 
 
    addFive := addN(5) 
    result := addN(6)  
    //5 + 6 must print 7 
    
    println(result) 
}

The addN variable points to a function that returns another function. But the returned function has the context of the m parameter within it. Every call to addN will create a new function with a fixed m value, so we can have main addN functions, each adding a different value.

This ability of closures is very useful to create libraries or deal with functions with unsupported types.

Creating errors, handling errors and returning errors.

Errors are extensively used in Go, probably thanks to its simplicity. To create an error simply make a call to errors.New(string) with the text you want to create on the error. For example:

err := errors.New("Error example") 

As we have seen before, we can return errors to a function. To handle an error you'll see the following pattern extensively in Go code:

func main(){ 
    err := doesReturnError() 
    if err != nil { 
        panic(err) 
    } 
} 
 
func doesReturnError() error { 
    err := errors.New("this function simply returns an error") 
    return err 
} 

Function with undetermined number of parameters

Functions can be declared as variadic. This means that its number of arguments can vary. What this does is to provide an array to the scope of the function that contains the arguments that the function was called with. This is convenient if you don't want to force the user to provide an array when using this function. For example:

func main() { 
    fmt.Printf("%d\n", sum(1,2,3)) 
    fmt.Printf("%d\n", sum(4,5,6,7,8)) 
} 
 
func sum(args ...int) (result int) { 
    for _, v := range args { 
        result += v 
    } 
    return 
} 

In this example, we have a sum function that will return the sum of all its arguments but take a closer look at the main function where we call sum. As you can see now, first we call sum with three arguments and then with five arguments. For sum functions, it doesn't matter how many arguments you pass as it treats its arguments as an array all in all. So on our sum definition, we simply iterate over the array to add each number to the result integer.

Naming returned types

Have you realized that we have given a name to the returned type? Usually, our declaration would be written as func sum(args int) int but you can also name the variable that you'll use within the function as a return value. Naming the variable in the return type would also zero-value it (in this case, an int will be initialized as zero). At the end, you just need to return the function (without value) and it will take the respective variable from the scope as returned value. This also makes easier to follow the mutation that the returning variable is suffering as well as to ensure that you aren't returning a mutated argument.

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 $15.99/month. Cancel anytime