Tutorials Logic, IN info@tutorialslogic.com
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Website Development
Practice
Quiz Challenge Interview Questions Certification Practice
Tools
Online Compiler JSON Formatter Regex Tester CSS Unit Converter Color Picker
Compiler Tools

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.

PartExampleMeaning
KeywordfuncStarts a function declaration
Parametersa int, b intInputs accepted by the function
Return typeintValue returned by the 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
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 are a major Golang feature. The most common pattern returns a useful value plus an error. This makes failure visible in the signature and forces callers to decide what to do.

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
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 StyleBest Use
Explicit return valuesMost normal functions
Named return valuesShort functions where names clarify meaning
Naked returnAvoid in long functions because it hides what returns
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
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
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
func readConfig(path string) ([]byte, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    return io.ReadAll(file)
}
Key Takeaways
  • 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.

Ready to Level Up Your Skills?

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