Can we have function pointers in Go?

Viewed 84498

I was learning about pointers in Go. And managed to write something like:

func hello(){

       fmt.Println("Hello World")
}

func main(){

       pfunc := hello     //pfunc is a pointer to the function "hello"
       pfunc()            //calling pfunc prints "Hello World" similar to hello function
}

Is there a way to declare the function pointer without defining it as done above? Can we write something like we do in C?

e.g. void (*pfunc)(void);

7 Answers

A function is also a type in Go. So you can essentially create a variable of type func signature. So following would work;

var pfunc func(string)

This variable can point to any function that take string as argument and returns nothing. Following piece of code works well.

package main

import "fmt"

func SayHello(to string) {
    fmt.Printf("Hello, %s!\n", to)
}

func main() {
    var pfunc func(string)

    pfunc = SayHello

    pfunc("world")
}

Array based function pointer solution

package main

import (
    "fmt"
)

type pfunc func(string, int)int

func testCase1(toStr string, toInt int)int {
    fmt.Printf("1st Function Call %s %d\n",toStr, toInt)
    return toInt
}

func testCase2(toStr string, toInt int)int {
    fmt.Printf("2nd Function Call %s %d\n",toStr, toInt)
    return toInt
}

func testCase3(toStr string, toInt int)int {
    fmt.Printf("3rd Function Call %s %d\n",toStr, toInt)
    return toInt
}

func main() {
        
    funcArray := []pfunc{testCase1,testCase2,testCase3} 
    
    for n:=range funcArray {
        result := funcArray[n]("Test", n)
        fmt.Printf("Run Test Case #%d reference %v result %d\n",n, funcArray[n], result)
    }
}

A different way to approach it is to define an interface

type command interface {
      DoLoop()
}

implement a struct that implements it

type Delete struct {
      instance string
}

func (dev Delete) DoLoop() {
      fmt.Println("input: delete ")
}

Create map that contains the struct

 mainFuncTable = make(map[string]command)
 mainFuncTable["delete"] = Delete{"new"}

the call the function

func route(command string) {
      cmd := mainFuncTable[command]
      cmd.DoLoop()
}

It's a little indirect but it works

I have taken reference from function pointer in c language and callback function from JavaScript

In c language we use function pointer to pass function as an argument to another function as function pointer act as a variable.

#include <stdio.h>

int add(int x, int y) {
    return x + y;
}

int sub(int x, int y) {
    return x - y;
}

int calc(int (*fp)(int, int), int a, int b) {
    return (*fp)(a, b);
}

int main() {
   
    printf("%d\n", calc(add, 5, 6)); // 11  
    printf("%d\n", calc(sub, 9, 6)); // 3
    
    return 0;
}

In JavaScript we can directly pass function as an argument

/* JavaScript Code Snippet */
var foo = function() {
    alert("Foo");
}

function bar(f) {
    f();
}

bar(foo)

I tried to replicate same scenario in Go Here the user of cacl function doesn't need to worry about what is inside the add function

The user just need to know what functionality he/she needs to perform based on which he/she pass function name as argument to calc function

package main
import "fmt"

func add(x, y int) int {
    return x + y;
}

func sub(x, y int) int {
    return x - y;
}

func calc(fp func(int, int) int, x, y int) {
    fmt.Println(fp(x, y));
}

func main() {
    calc(add, 5, 6); // 11
    calc(sub, 7, 4); // 3

    calc(func(x, y int) int{
        return x * y;
    }, 5, 3); //this will print 15

}

Also if required we can create anonymous function like we created for multiplication

And if you want to use pointer to function directly then following snippet would work

package main
import "fmt"

func greet(){
    fmt.Println("Hello World")
}

func main() {

    fptr := greet
    fmt.Println(fptr) //this will print address
    fptr()
}

I hope this will help.

Related