203

I'm porting a C library to Go. A C function (with varargs) is defined like this:

curl_easy_setopt(CURL *curl, CURLoption option, ...); 

So I created wrapper C functions:

curl_wrapper_easy_setopt_str(CURL *curl, CURLoption option, char* param);
curl_wrapper_easy_setopt_long(CURL *curl, CURLoption option, long param);

If I define function in Go like this:

func (e *Easy)SetOption(option Option, param string) {
    e.code = Code(C.curl_wrapper_easy_setopt_str(e.curl, C.CURLoption(option), C.CString(param)))
}

func (e *Easy)SetOption(option Option, param long) {
    e.code = Code(C.curl_wrapper_easy_setopt_long(e.curl, C.CURLoption(option), C.long(param)))
}

The Go compiler complains:

*Easy·SetOption redeclared in this block

So does Go support function (method) overloading, or does this error mean something else?

0

6 Answers 6

248

No it does not.

See the Go Language FAQ, and specifically the section on overloading.

Method dispatch is simplified if it doesn't need to do type matching as well. Experience with other languages told us that having a variety of methods with the same name but different signatures was occasionally useful but that it could also be confusing and fragile in practice. Matching only by name and requiring consistency in the types was a major simplifying decision in Go's type system.

Update: 2016-04-07

While Go still does not have overloaded functions (and probably never will), the most useful feature of overloading, that of calling a function with optional arguments and inferring defaults for those omitted can be simulated using a variadic function, which has since been added. But this comes at the loss of type checking.

Sign up to request clarification or add additional context in comments.

4 Comments

"was occasionally useful"? what if I want to write a function that sums numbers? that can accept two arguments of int32, int64, uint32, uint64 and strings? In JS, which does not allow overloading, I could use "number" type, but in strictly typed language like Go I must write tons of functions with slightly different names :/
@VityaSchel Well, to be fair, JS doesn't have int32 ... uint64; it has only one intrinsic numeric type, number -- so that's apples and oranges. And you wouldn't write tons, you'd just write the (uint64,uint64) function and allow the system to widen them, while converting Strings to uint64 at the call point.
Has anyone created a go generate tool for playerParams as advocated in the changelog.ca article?
Functional options is a something that really helpful but require to write a too much boilerplate. To make life easier, I built a code generator. All you need to do is define a structure with some fields, where each field represents an option: github.com/kazhuravlev/options-gen
32

According to this, it doesn't: http://golang.org/doc/go_for_cpp_programmers.html

In the Conceptual Differences section, it says:

Go does not support function overloading and does not support user defined operators.

Comments

29

No, Go doesn't have overloading.

Overloading adds compiler complexity and will likely never be added.

As Lawrence Dol mentioned, you could use a variadic function at the cost of no type checking.

Your best bet is to use generics and type constraints that were added in Go 1.18

To answer VityaSchel's question, in the comments of Lawrence's answer, of how to make a generic sum function, I've written one below.

https://go.dev/play/p/hRhInhsAJFT


package main

import "fmt"

type Number interface {
  int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64
}

func Sum[number Number](a number, b number) number {
  return a + b
}

func main() {
  var a float64 = 5.1
  var b float64 = 3.2
  println(Sum(a, b))

  var a2 int = 5
  var b2 int = 3
  println(Sum(a2, b2))
}

Comments

10

Even though this question is really old, what I still want to say is that there is a way to acheive something close to overloading functions. Although it may not make the code so easy to read.

Say if you want to overload the funtion Test():

func Test(a int) {
    println(a);
}
func Test(a int, b string) {
    println(a);
    println(b);
}

The code above will cause error. However if you redefine the first Test() to Test1() and the second to Test2(), and define a new function Test() using go's ..., you would be able to call the function Test() the way it is overloaded. code:

package main;

func Test1(a int) {
    println(a);
}
func Test2(a int, b string) {
    println(a);
    println(b);
}
func Test(a int, bs ...string) {
    if len(bs) == 0 {
        Test1(a);
    } else {
        Test2(a, bs[0]);
    }
}
func main() {
    Test(1);
    Test(1, "aaa");
}

output:

1
1
aaa

see more at: https://golangbyexample.com/function-method-overloading-golang/ (I'm not the author of this linked article but personally consider it useful)

6 Comments

this is ugleeeee
@SergeyKolesnik It is, lol
since we are talking "ugly", I suggest you try function overloading via "dummy" receiver parameters. I suppose overloading for receivers is allowed since otherwise it would be impossible to have interfaces. Just for the sake of experiment. I can't see how it would improve anything
@SergeyKolesnik You mean something like this? go.dev/play/p/CoDbx9cPUY2 It looks fine but you'd probably need to define a large number of types when there is a lot of function overloading required, which could make the typenames quite long and "ugly"
I'm shocked that it's has so many upvotes, newcomers to Golang can think that it's ok and use this snippet in real life projects :(
|
1

You can also do it by making the function variadic using ...interface{}, this will make the param as of type Slice, and then just take off the first value in it using param[0]

func (e *Easy)SetOption(option Option, param ...interface{}) {
    e.code = Code(C.curl_wrapper_easy_setopt_str(e.curl, C.CURLoption(option), C.CString(param[0])))
}

now argument of any type is valid, but at the cost of type checking

Comments

1

As others said the answer is No!

But Golang provides another feature called as receivers which can be used to write something close to overloading:

Basically we are using receiver as a way to differentiate the functions and are able to use same function name for two different functions which can have same args or diff args, but the only caveat is that you can invoke the function only with receiver as its attached to it !

I doubt this kind of code could be useful as it can be confusing, but nevertheless its possible :)

package main

import "fmt"

type hello struct {
    name string
}

func main() {
    fmt.Println(returnNumber(777))
    h := hello{name: "hello"}
    fmt.Println(h.returnNumber("world"))
}

func returnNumber(i int) int {
    return i
}

func (h hello) returnNumber(s string) string {
    return h.name + s
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.