Skip to content

cwchentw/overloading-golang

Repository files navigation

Function Overloading in Go

A lightweight argument checker to simulate function overloading in Golang.

Introduction

Go does not support function or method overloading. One common workaround is using variadic parameters:

func Foo(args ...interface{}) interface{} {
    // Process args
}

While flexible, this approach sacrifices type safety and often leads to repetitive, error-prone argument checking. This package provides tools to simplify that process.

Another alternative is to use a map[string]interface{} for named arguments:

func Bar(arg map[string]interface{}) interface{} {
    // Process arg
}

This package supports both approaches, offering helpers to validate positional and named arguments.

⚠️ Note: Variadic overloading is a powerful but debatable technique in Go. Use it wisely and sparingly.


Usage

1. List-Based Overloading

Support for multiple type signatures:

package main

import (
	ov "github.com/cwchentw/overloading-golang"
	"log"
)

var checker *ov.ListChecker

func init() {
	checker = ov.NewListChecker(
		ov.NewListRule(
			ov.NewArgument("int"),
			ov.NewArgument("int")),
		ov.NewListRule(
			ov.NewArgument("float64"),
			ov.NewArgument("float64")),
	)
}

func main() {
	n := add(3, 2).(int)
	if n != 5 {
		log.Fatal("Incorrect result")
	}
}

func add(args ...interface{}) interface{} {
	out := checker.Check(args)

	switch out[0].(type) {
	case int:
		return out[0].(int) + out[1].(int)
	case float64:
		return out[0].(float64) + out[1].(float64)
	default:
		panic("Unsupported type")
	}
}

2. Optional Arguments

Support for default values:

package main

import (
	ov "github.com/cwchentw/overloading-golang"
	"log"
)

var checker *ov.ListChecker

func init() {
	checker = ov.NewListChecker(
		ov.NewListRule(
			ov.NewArgument("int"),
			ov.NewArgument("int", 3)),
	)
}

func main() {
	n := add(3)
	if n != 6 {
		log.Fatal("Incorrect result")
	}
}

func add(args ...interface{}) int {
	out := checker.Check(args)
	return out[0].(int) + out[1].(int)
}

3. Map-Based Overloading

Support for named parameters using maps:

package main

import (
	ov "github.com/cwchentw/overloading-golang"
	"log"
	"reflect"
)

var checker *ov.MapChecker

func init() {
	checker = ov.NewMapChecker(
		ov.NewMapRule(
			"x", ov.NewArgument("int"),
			"y", ov.NewArgument("int")),
		ov.NewMapRule(
			"x", ov.NewArgument("float64"),
			"y", ov.NewArgument("float64")),
	)
}

func main() {
	arg := map[string]interface{}{ "x": 3.0, "y": 2.0 }
	n := add(arg).(float64)
	if n != 5.0 {
		log.Fatal("Incorrect result")
	}
}

func add(arg map[string]interface{}) interface{} {
	out := checker.Check(arg)
	switch reflect.TypeOf(out["x"]).String() {
	case "int":
		return out["x"].(int) + out["y"].(int)
	case "float64":
		return out["x"].(float64) + out["y"].(float64)
	default:
		panic("Unsupported type")
	}
}

License

MIT License Copyright (c) 2017 Modified and maintained by ByteBard

About

Function Overloading in Golang

Topics

Resources

Stars

Watchers

Forks

Languages