Go Concepts - Functions

From NovaOrdis Knowledge Base
Revision as of 04:28, 30 March 2016 by Ovidiu (talk | contribs) (→‎Methods)
Jump to navigation Jump to search

External

Internal

Function Definition

A function declaration starts with the func keyword and it consists in a series of statements applied on a number of inputs, resulting in a number of outputs. Same inputs will always result in the same outputs. Function do not depend on a type instance's state. From this perspective, functions are conceptually different from methods.

The parameters and the return types are known as the function's signature.

Syntax

func <name>(
    [parameter-identifier1] [type1], [parameter-identifier2] [type2], ...) 
    [(<return-type1>, [return-type2], ...)] {

   // function's body
   statement1
   statement2
   ...

   return <return-value1>, <return-value2>
}
func add(a int, b int) int {
   return a + b;
}

The return type declarations are optional, if the function does not return anything.

Multiple Return Values

A function may return one or more results:

func add(a int, b int) (int, int) {
   return a + b, a - b;
}

Also see Communicating Errors.

Return Types can Have Names

func f() (r int) {
   r = 1
   return
}

Varidic Functions

Variadic parameters are declared using ellipsis (...).

func f(args ...int) int {

    //
    // range can be used to iterate over the individual parameters
    //
   for _, arg := range args {
        // ...
   }
}

Also see:

range

A slice can be "converted" into its individual components which can be passed as individual arguments to a variadic function, by appending an ellipsis (...) to the slice identifier:

s := []int{1, 2, 3}
f(s...)

Functions and Variable Scopes

A function does not have access to variables declares in functions that call it.

A function does have access to package level variables declared in the function's package.

Also see:

Variable Scopes

Pass by Value vs. Pass by Reference

In Go, all variables are passed by value: when an argument is passed to a function, that argument is copied on the stack.

This is true for built-in types and for user defined types (structs). Because of that, if you want to change a struct inside a function, you should pass a pointer to that struct, not the struct itself.

Even for pointer variables, since the value of the pointer is a memory address, passing pointer variables is still considered pass by value.

Closures

Closures

defer

The defer keyword schedules the function it is invoked with to be executed immediately after the function it is invoked from exits, irrespective of how the function exits (even with a panic). The execution is done on the same thread.

defer is used in Go idioms where a resource needs to be closed after it was opened: it keeps the "close" call near the "open" call, so the code is easier to understand. The recommended way to do it is:

f, _ := os.Open(filename)
defer f.Close()

Function Literals

The main() Function

Compiling an Executable

Built-in Functions

The built-in functions are available by default, without the need to import any package. They are what the specification calls pre-defined function identifiers. Their semantics depends on the arguments.

Conversion between Types

Conversions between types look like function invocations, see Conversion between Types.

Methods

A method defines the behavior of a type, and it relies on the state of an instance of the type. The method will - and it is supposed to - change the state. From this point of view, the method is conceptually different from a function.

Lexically, methods are declared independently from the type they are related to: they can declared in a different section of the file from where the type is declared, or in a different file altogether, as long as that file belongs to the same package.

A method is always exported by the package it is enclosed in.

Syntax

A method declaration is similar to a function's, except that in between the func keyword and the name of function we add a receiver. The receiver syntax is similar to a function's parameters: (name type):

func (<receiver>) <method-name> (...) {

    // the rest of declaration is similar to a function's
    ...
}

Example:

func (bagPtr *Bag) changeBagsColor(color string) {
...
}

Difference between Functions and Methods

Receivers

Value Receivers

Pointer Receivers