Can you pass a function as a parameter? Yes, and here's why it changes everything
\n\nHave you ever wondered if you can pass one function inside another in Go, like a regular variable? If you come from the world of Python or JavaScript, this is a familiar pattern for you. But in Go, despite all its strictness, functions as parameters is not just "possible," it is one of the most powerful tools in the language.
\n\nI remember my first encounter with this concept: I was writing a utility for processing logs and realized I was copy-pasting the same loop with different logic inside. The solution came when I realized I could simply pass the needed function as an argument. The code became cleaner, shorter, and more understandable. In this article, I will show you how to master passing a function to a function in Go — from simple examples to real-world patterns you can use at work tomorrow.
\n\nBy the way, here at PythonLib we often see questions like "Can functions be passed as parameters?" on Stack Overflow with thousands of views. Let's finally break down this topic once and for all using Go as an example.
\n\nWhat are functions as parameters in Go?
\n\nIn Go, functions are first-class objects. This means they can be:
\n- \n
- Assigned to variables \n
- Passed to other functions \n
- Returned from functions \n
- Stored in structs and slices \n
When we talk about a function as a parameter, we mean that one function accepts another function as an argument and calls it inside itself. Sounds complicated? It's actually simpler than it seems.
\n\nSyntax: how to declare a function that accepts another function
\n\nIn Go, you need to explicitly specify the type of the function parameter. It looks like this:
\n\n// Declaring a function type\ntype Transformer func(string) string\n\n// A function that accepts another function\nfunc processText(text string, transform Transformer) string {\n return transform(text)\n}\n\nOr you can declare the type directly in the signature:
\n\nfunc processText(text string, transform func(string) string) string {\n return transform(text)\n}\n\nBoth options work. The first is more convenient if you plan to reuse the type. The second is for quick solutions.
\n\nSimple example: passing a greeting function
\n\nLet's write something practical. Imagine you have a function that formats a user's name, and you want to plug in different greetings:
\n\npackage main\n\nimport "fmt"\n\n// Type for the greeting function\ntype Greeter func(name string) string\n\n// Function that accepts a greeting\nfunc greetUser(name string, greeter Greeter) {\n message := greeter(name)\n fmt.Println(message)\n}\n\nfunc main() {\n // Normal greeting\n normalGreet := func(name string) string {\n return "Hello, " + name + "!"\n }\n\n // Formal greeting\n formalGreet := func(name string) string {\n return "Dear " + name + ", good afternoon."\n }\n\n greetUser("Anna", normalGreet)\n greetUser("Anna", formalGreet)\n}\n\nOutput:
\nHello, Anna!\nDear Anna, good afternoon.\n\nSee? We simply passed different functions into the same greetUser. This is passing a function as an argument in action.
Callback functions: when you need to process the result
\n\nOne of the most common use cases for functions as parameters is callbacks. You perform some operation and call the passed function when the operation is complete.
\n\npackage main\n\nimport (\n "fmt"\n "time"\n)\n\n// Function that simulates a long data load\nfunc fetchData(callback func(string)) {\n fmt.Println("Loading data...")\n time.Sleep(2 * time.Second) // Simulating a delay\n data := "Important data from the database"\n callback(data)