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.")
}
How it works:
- We define
func sayHello()
to encapsulate the printing logic. - Inside
main
, we callsayHello()
by its name, followed by parentheses()
. The program jumps to the function, runs the code inside it, and then returns tomain
.
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")
}
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
}
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)
}
}
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)