Basics

Simulate optional parameters


type MyFuncOpts struct {
	FirstName string
	LastName string
	Age int
}


func printNameAge(opts MyFuncOpts) error {
	if opts.LastName != "" {
		fmt.Println(opts.LastName)
	}
	if opts.Age != 0 {
		fmt.Println("Age =", opts.Age)
		} else { 
			fmt.Println("No age provided")
	}
	return nil
}


func test() {
	printNameAge(MyFuncOpts {
		LastName: "Clayton",
	})
}


test()
Clayton
No age provided

Variadic input parameters and slices


func addTo(base int, values ...int) []int {
	out := make([]int, 0, len(values))
	for _, v := range values {
		out = append(out, base+v)
	}
	return out
}

Standard call


sum := addTo(29,123,14,13)
fmt.Println(sum)
[152 43 42]

Spread an array into the parameters


a := []int{20,30,40}
sumSpread := addTo(10, a...)
fmt.Println(sumSpread)
[30 40 50]

Named return values


func divAndRemainder(numerator int, denominator int) (result int, remainder int, err error) {
	if denominator == 0 {
		err = errors.New("Cannot divide by zero")
		return result, remainder, err
	}
	result, remainder = numerator/denominator, numerator%denominator
	return result, remainder, err
}


x, y, err := divAndRemainder(5, 0)
if err != nil {
	fmt.Println("Oh no an error:", err)
	os.Exit(1)
}
fmt.Println(x, y, err)
No age provided
[152 43 42]
[30 40 50]
gobook-output-start
Oh no an error: Cannot divide by zero
exit status 1

Blank return (Go community says this is bad idea as it's unclear!)


func divAndRemainder(numerator, denominator int) (result int, remainder int, err error) {
	if denominator == 0 {
		return 0, 0, errors.New("Cannot divide by zero")
	}
	result, remainder = numerator/denominator, numerator%denominator
	return
}
/tmp/main.go:45:6: divAndRemainder redeclared in this block
	previous declaration at /tmp/main.go:37:86


x, y, z := divAndRemainder(10, 2)
fmt.Println(x, y, z)
5 0 <nil>

Anonymous function


	for i := 0; i < 3; i++ {
		x := func(j int) int {
			fmt.Println("Printing", j, "from inside of an anonymous function")
			return i
		}(i)
		fmt.Println("Printing", x, "from the value returned")
	}
Printing 0 from inside of an anonymous function
Printing 0 from the value returned
Printing 1 from inside of an anonymous function
Printing 1 from the value returned
Printing 2 from inside of an anonymous function
Printing 2 from the value returned

First Class Functions


func add(i int, j int) int { return i + j }
func sub(i int, j int) int { return i - j }
func mul(i int, j int) int { return i * j }
func div(i int, j int) int { return i / j }


// Documentation for type
type opFuncType func(int, int) int

var opMap = map[string]opFuncType{
	"+": add,
	"-": sub,
	"*": mul,
	"/": div,
}
/tmp/main.go:74:6: opMap declared but not used


func run() {
	expressions := [][]string{
		{"2", "-", "3"},
		{"2", "+", "3"},
		{"2", "*", "3"},
		{"2", "/", "3"},
		{"2", "%", "3"},
		{"two", "plus", "three"},
		{"5"},
	}
	for _, expression := range expressions {
		if len(expression) != 3 {
			fmt.Println("invalid expression", expression, "(needs three parameters)")
			continue
		}
		p1, err := strconv.Atoi(expression[0])
		if err != nil {
			fmt.Println(err)
			continue
		}
		op := expression[1]
		opFunc, ok := opMap[op]
		if !ok {
			fmt.Println("unsupported operator:", op)
			continue
		}
		p2, err := strconv.Atoi(expression[2])
		if err != nil {
			fmt.Println(err)
			continue
		}
		result := opFunc(p1, p2)
		fmt.Println(result)
	}
}


run()
-1
5
6
0
unsupported operator: %
strconv.Atoi: parsing "two": invalid syntax
invalid expression [5] (needs three parameters)