DEV Community

Andi
Andi

Posted on

Go (Golang) Basic - Functions

From a Long Script to Organized Blocks

As our programs grow, putting all our logic inside the main function can become messy and hard to manage. If we need to perform the same task multiple times, we'd have to copy and paste our code, which is a recipe for disaster.

The solution is to organize our code into reusable, named blocks. In Go, as in most programming languages, these blocks are called Functions.

Analogy: A coffee machine. Instead of manually grinding beans, tamping, and pulling a shot every time, you just press the "Espresso" button. That button is a function. It bundles a series of steps into one simple action.

1. Defining and Calling a Simple Function

A function is a block of code that performs a specific task. Let's create our first function.

package main

import "fmt"

// 1. We define our function here
func sayHello() {
    fmt.Println("Hello from a function!")
}

func main() {
    fmt.Println("Starting the program...")

    // 2. We call the function by its name
    sayHello()

    fmt.Println("Program finished.")
}
Enter fullscreen mode Exit fullscreen mode

How it works:

  1. We define func sayHello() to encapsulate the printing logic.
  2. Inside main, we call sayHello() by its name, followed by parentheses (). The program jumps to the function, runs the code inside it, and then returns to main.

2. Functions with Parameters (Providing Input)

What if we want our function to be more flexible? For example, what if we want to greet a specific person? We can pass data into a function through parameters.

Parameters are variables that a function accepts as input.

package main

import "fmt"

// This function accepts one parameter called 'name' of type 'string'
func greet(name string) {
    fmt.Println("Hello,", name)
}

func main() {
    greet("Budi") // "Budi" is the argument we pass to the 'name' parameter
    greet("Siti")
}
Enter fullscreen mode Exit fullscreen mode

Now our greet function is much more reusable!

3. Functions with Return Values (Getting Output)

Functions are not just for doing things; they can also give back a result after they've finished their work. This is called a return value.

Analogy: A calculator. You provide input (numbers and an operation), and it returns the answer to you.

How to Return a Single Value

You specify the type of data the function will return right after its parameters.

package main

import "fmt"

// This function accepts a 'string' and will return a 'string'
func createGreeting(name string) string {
    greeting := "Hello from a function, " + name
    return greeting // The 'return' keyword sends the value back
}

func main() {
    // We capture the returned value in a variable
    message := createGreeting("Charlie")
    fmt.Println(message) // Prints: Hello from a function, Charlie
}
Enter fullscreen mode Exit fullscreen mode

4. The Go Superpower: Multiple Returns

Here's a feature that makes Go stand out: a function can return more than one value. This is extremely common in Go, especially for functions that might fail.

The standard pattern is to return (the result, an error).

How to Return Multiple Values

Let's create a safe division function that returns the result and a potential error if we try to divide by zero.

package main

import (
    "errors"
    "fmt"
)

// This function returns two values: a float64 AND an error
func divide(a float64, b float64) (float64, error) {
    // If the divisor is zero, it's an error
    if b == 0 {
        // We return a zero value for the number and a new error message
        return 0, errors.New("cannot divide by zero")
    }

    // If everything is okay, we return the result and 'nil' for the error
    // 'nil' is Go's way of saying "nothing" or "no error"
    return a / b, nil
}

func main() {
    // --- Successful case ---
    result, err := divide(10.0, 2.0)
    if err != nil {
        // This block is skipped because 'err' is nil
        fmt.Println("Error:", err)
    } else {
        fmt.Println("Result 1:", result)
    }

    // --- Failure case ---
    result2, err2 := divide(10.0, 0)
    if err2 != nil {
        // This block runs because an error was returned
        fmt.Println("Error:", err2)
    } else {
        fmt.Println("Result 2:", result2)
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Functions are the cornerstone of writing well-structured and maintainable code. You've now learned how to:

  • Define and call simple functions.
  • Pass data into them using parameters.
  • Get results back using single and multiple return values.

By breaking your logic into functions, you're making your code cleaner, easier to debug, and much more powerful.

In the next part, we'll learn how to create our own custom data types using Structs and attach functions directly to them using Methods. See you there!

Top comments (0)