Functions
Basic syntax:
- func foo() {
...
}
Parameters:
- Comma delimited list of variable and types
- func foo(bar string, baz int)
- Parameters of same type list type once, at the end
- func foo(bar, baz int)
- When pointers are passed in, the function can change the value in the caller
- This is always true for data of slices and maps
- Use variadic parameters to send list of same types in
- Must be last parameter
- Received as a slice
- func foo(bar string, baz ...int)
Return Values:
- Single return values just list type
- func foo() int
- Multiple return values list types surrounded by parentheses
- func foo() (int, error)
- The (result type, error) paradigm is a very common idiom
- Can use named return values
- Initializes returned variable
- Return using return keyword on its own
- Can return addresses of local variables
- Automatically promoted from local memory (stack) to shared memory (heap)
Anonymous Functions:
- Functions don't have names if they are:
- Immediately Invoked Function Expressions (IIFE), I.E:
- func() {
...
}()
- Assigned to a variable or passed as an argument to a function
- a := func() {
...
}
a()
Functions as Types:
- Can assign functions to variables or use as arguments and return values in functions
- Type signature is like function signature, with no parameter names
- var f func(string, string, string) (int, error)
Methods:
- Function that executes in context of a type
- Format:
- func (g greeter) greet() {
...
}
- Receiver can be value or pointer
- Value receiver gets copy of type
- Pointer receiver gets pointer to type
Interfaces
// Basic syntax:
type Writer interface {
Write([]byte) (int, error)
}
type ConsoleWriter struct{}
func (cw ConsoleWriter) Write(data[]byte) (int, error){
n, err := fmt.Println(string(data))
return n, err
}
// Composing Interfaces:
type Writer interface {
Write([]byte) (int, error)
}
type Closer interface {
Close() error
}
type WriterCloser interface {
Writer
Closer
}
// Type Conversion:
var wc WriterCloser = NewBufferedWriterCloser()
bwc := wc.(*BufferedWriterCloser)
Implementing with Values vs. Pointers:
- Method set of "value" is all methods with value receivers
- Method set of pointer is all methods, regardless of receiver type
// Best Practices:
- Use many, small interfaces
- Single method interfaces are some of the most powerful and flexible Go-lang tools
- io.Writer, io.Reader, interface{}
- Don't export interfaces for types that will be consumed
- Do export interfaces for types that will be used by packages
- Design functions and methods to receive interfaces whenever possible
d
