Golang Backend Real-World (Part 5): Functions, Parameters, Return Values & Error Handling
  • Golang
  • Golang Real-World (Part 5): Functions, Parameters, Return Values & Error Handling

    Functions in Real-World Golang

    Functions are one of the core building blocks of every Golang backend.
    In real-world projects, functions are used everywhere: handlers, services, repositories, utilities, and background jobs.

    This part will help you master:

    • Function declaration
    • Input parameters
    • Multiple return values
    • Error handling
    • Variadic functions
    • Named returns
    • Higher-order functions
    • Real-world backend examples

    1. Function Declaration

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

    You can shorten parameters with the same type:

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

    2. Multiple Return Values (Very Common in Backend)

    Golang supports multiple return values — extremely useful for error handling.

    func divide(a, b float64) (float64, error) {
        if b == 0 {
            return 0, fmt.Errorf("cannot divide by zero")
        }
        return a / b, nil
    }
    

    Usage:

    result, err := divide(10, 2)
    if err != nil {
        log.Println(err)
    }
    

    3. Error Handling Pattern (Idiomatic Go)

    Golang does not use exceptions.

    Instead, functions return errors explicitly:

    func findUser(id int) (*User, error) {
        user, err := db.FindByID(id)
        if err != nil {
            return nil, err
        }
        return user, nil
    }
    

    Standard pattern:

    if err != nil {
        return ..., err
    }
    

    This is exactly how real services & repositories are written.


    4. Variadic Functions

    Functions that accept unlimited parameters:

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

    Usage:

    total := sum(1, 2, 3, 4)
    

    5. Named Return Values

    Sometimes useful for service functions and utilities.

    func compute(a, b int) (result int) {
        result = a + b
        return
    }
    

    However, use this carefully:
    ✔ Clean for small utilities
    ✖ Avoid for complex functions (readability issue)


    6. Functions as Values (Higher-Order Functions)

    You can pass functions around:

    func apply(x int, fn func(int) int) int {
        return fn(x)
    }
    

    Usage:

    square := func(n int) int { return n * n }
    println(apply(5, square))  // Output: 25
    

    This is powerful for middleware, callbacks, and reusable logic.


    7. Real-World Example: Service Layer Function

    This is how a typical service function looks in a clean-architecture Golang backend:

    func (s *UserService) CreateUser(input CreateUserDTO) (*User, error) {
        if input.Email == "" {
            return nil, fmt.Errorf("email is required")
        }
    
        user := User{
            Name:  input.Name,
            Email: input.Email,
        }
    
        savedUser, err := s.repo.Create(user)
        if err != nil {
            return nil, err
        }
    
        return savedUser, nil
    }
    

    Patterns used here:

    • Input parameters (input)
    • Multiple return (*User, error)
    • Validation logic
    • Service → repository call
    • Error propagation

    8. Real-World Example: Handler Function

    Handlers are also regular functions:

    func (h *UserHandler) CreateUser(c *gin.Context) {
        var dto CreateUserDTO
    
        if err := c.ShouldBindJSON(&dto); err != nil {
            c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
            return
        }
    
        user, err := h.service.CreateUser(dto)
        if err != nil {
            c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
            return
        }
    
        c.JSON(http.StatusOK, user)
    }
    

    Demonstrates:

    • Parameter binding
    • Calling service functions
    • Error handling
    • JSON response

    🎯 Summary

    In this part, you learned:

    ✔ Function declaration
    ✔ Parameters & return types
    ✔ Multiple return values
    ✔ Real-world error handling
    ✔ Variadic functions
    ✔ Named returns
    ✔ Higher-order functions
    ✔ Service & handler examples

    Leaf

    "Thành công nuôi dưỡng sự hoàn hảo. Sự hoàn hảo lại nuôi lớn thất bại. Chỉ có trí tưởng tượng mới tồn tại."
    3 mins