Tutorials Logic, IN info@tutorialslogic.com

Golang Functions: Parameters, Return Values, Variadic and Closures

Function Basics

Functions are declared with the func keyword. Parameter names come before their types, and the return type comes after the parameter list.

Keep Golang functions focused. A function should usually do one clear thing: parse input, validate a value, calculate a result, call a dependency, or write a response. Smaller functions are easier to test and easier to reuse.

Part Example Meaning
Keyword func Starts a function declaration
Parameters a int, b int Inputs accepted by the function
Return type int Value returned by the function

Simple Function

Simple Function
package main

import "fmt"

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

func main() {
    fmt.Println(add(10, 20))
}

Short Parameter Syntax

When consecutive parameters share the same type, you can write the type once after the last name. This is common in small helpers and mathematical functions.

Do not over-compress signatures if readability suffers. A longer but clearer signature is better than a clever one, especially when parameters represent different concepts.

Shared Parameter Type

Shared Parameter Type
func multiply(width, height int) int {
    return width * height
}

func formatName(first, last string) string {
    return first + " " + last
}

func createUser(name string, age int, active bool) User {
    return User{Name: name, Age: age, Active: active}
}

Multiple Return Values

Multiple return values let a Go function return its result and its failure state together. The usual shape is a value followed by an error, so the caller can inspect both in one assignment and stop immediately when the error is not nil.

Return the zero value for the successful result when returning an error. For example, return 0, err for a number, "", err for a string, or nil, err for a pointer, slice, map, or interface.

Result and Error

Result and Error
package main

import (
    "errors"
    "fmt"
)

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, errors.New("division by zero")
    }
    return a / b, nil
}

func main() {
    result, err := divide(20, 4)
    if err != nil {
        fmt.Println("error:", err)
        return
    }
    fmt.Println(result)
}

Named Return Values

Golang allows named return values. They can improve documentation for short functions, but they can also make longer functions harder to follow if values are changed far from the return statement.

Use named returns carefully. In most application code, explicit return values are easier for beginners and reviewers to understand because the returned values are visible at the return line.

Return Style Best Use
Explicit return values Most normal functions
Named return values Short functions where names clarify meaning
Naked return Avoid in long functions because it hides what returns

Named Return Example

Named Return Example
func splitName(fullName string) (first string, last string) {
    parts := strings.Fields(fullName)
    if len(parts) == 0 {
        return "", ""
    }
    if len(parts) == 1 {
        return parts[0], ""
    }
    return parts[0], parts[len(parts)-1]
}

Variadic Functions

A variadic parameter accepts zero or more values and behaves like a slice inside the function. Variadic functions are useful for logging fields, totals, middleware, optional labels, or functions where callers naturally pass a flexible number of values.

Only the final parameter can be variadic. If you already have a slice, pass it with ... to expand it into variadic arguments.

Variadic Function

Variadic Function
package main

import "fmt"

func sum(values ...int) int {
    total := 0
    for _, value := range values {
        total += value
    }
    return total
}

func main() {
    numbers := []int{10, 20, 30}
    fmt.Println(sum(1, 2, 3))
    fmt.Println(sum(numbers...))
}

Functions as Values and Closures

Functions are values in Golang. You can assign them to variables, pass them to another function, or return them from a function. This is useful for callbacks, middleware, sorting, filtering, and test hooks.

A closure remembers variables from the scope where it was created. Use closures carefully when they mutate captured variables, especially with goroutines.

Closure Counter

Closure Counter
func makeCounter() func() int {
    count := 0

    return func() int {
        count++
        return count
    }
}

counter := makeCounter()
fmt.Println(counter()) // 1
fmt.Println(counter()) // 2

Defer in Functions

defer schedules a function call to run when the surrounding function returns. It is commonly used to close files, unlock mutexes, finish spans, recover from panics at boundaries, or clean up temporary resources.

Deferred calls run in last-in, first-out order. Keep deferred work small and predictable so cleanup is easy to understand.

Cleanup with defer

Cleanup with defer
func readConfig(path string) ([]byte, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    return io.ReadAll(file)
}
Before you move on

Golang Functions: Parameters, Return Values, Variadic and Closures Mastery Check

7 checks
  • Golang functions use the func keyword.
  • Keep functions focused and signatures readable.
  • Multiple return values are common for result plus error.
  • Use named returns sparingly and avoid naked returns in long functions.
  • Variadic parameters behave like slices inside the function.
  • Functions can be passed around as values, and closures can capture outer variables.
  • defer is useful for predictable cleanup.
Next Step
Next Practice

Finish the concept here, then reinforce it with hands-on coding, interview prep, or a tool that matches the topic.

Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.