Does the Go language have function/method overloading? - go

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?

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.
For example: http://changelog.ca/log/2015/01/30/golang

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.

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)

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))
}

Related

How to distinguish between reference and value in golang

package main
type A struct {
Num int
}
func getA() A {
return A{Num: 10}
}
func main() {
if getA().Num == 10 {
// getA().Num = 20 // why not working
myA := getA()
myA.Num = 20
}
}
why "getA().Num = 20" line do not working?
I'm don't know the difference between
myA := getA()
myA.Num = 20
and
//getA().Num = 20 // why not working
I think it just two line and one line...
I'm more familiar with Java.
What I need to know to understand it?
I expected the code working correctly....
Tweak your function declaration like this, and it will work as you're expecting:
func getA() *A {
return &A{Num: 10}
}
What has changed is that getA returns a pointer to a value of type A.
In Java, class data types are always used as references (like a pointer), except the language doesn't use an explicit notation like this. So, writing Go code to use pointer types like *A is similar to what you're used to in Java.
The part that may confuse you is that Java doesn't have a direct equivalent for Go's non-pointer types, like the plain A in your Go code. In Java, you can only declare a class type, which always acts as a reference.

golang function type inheritance?

Consider this example in Go language:
type I interface {
get() string
}
type S struct {}
func (s *S) get() string {
return "here!"
}
var sSupplier = func() *S {
return &S{}
}
func foo(supplier func () I) {
i := supplier()
println(i)
}
func main() {
foo(sSupplier) // compile error, type mismatch
}
Type S inherit interface I. But apparently type func () *S does not inherit func () I, so I cannot call foo with sSupplier in place of the supplier function. Is there a way to fix it without forcing sSupplier to return type I?
In java you can use generics to do something like <T extends I> void foo(Supplier<T> supplier) {...} then call foo(sSupplier); with Supplier<S> sSupplier type. I'm not sure if similar approach is possible in go?
If you think for a bit about what generics do for you, they are really a way to ask the compiler to compile, on the spot, an anonymous wrapper function or lambda or whatever is needed to map from some concrete type. That is, given something like (I'll use C++ syntax here rather than Java as I'm much more familiar with C++):
template<T>
void f(T obj) {
// do stuff with the object
}
you're telling the compiler that when it sees f(int_value) it should build a function f that takes an int, and when it sees f(struct S) it should build a function f that takes a struct S, and so on. (This is a bit more natural in Java than it is in C++'s C underpinnings since Java does the whole argument-matching thing to decide which of these various f functions to call.)
In effect, instead of writing the actual function, you write a template—hence the C++ keyword—that the compiler can use to, at compile time, produce the function you really wanted. Since Go lacks generics, it lacks this sort of template-expansion trick.
That leaves you with several obvious alternatives, though. One is exemplified by go:generate (see, e.g., Explain go generate in this example). In this particularly simple case, though, you can just write the expansion yourself in line:
foo(func() I { return sSupplier() })
See a more complete example on the Go playground. I replacd your println(i) with fmt.Printf("%#v\n", i) to print the interface object's value in a slightly more useful form.

Type func with interface parameter incompatible error

I have declared a new type func that takes any value that conforms to interface{}. However, when I invoke a function that has been passed as an argument (conforming to that type specification) I get an error.
Can somebody explain why this is the case? Below is the simplest example I could recreate the issue with.
type myfunc func(x interface{})
func a(num int) {
return
}
func b(f myfunc) {
f(2)
return
}
func main() {
b(a) // error: cannot use a (type func(int)) as type myfunc in argument to b
return
}
The concept you're looking for here is variance in the type system. Some type systems and types support covariance and contravariance, but Go's interfaces do not.
While an int can be passed to a function that expects interface{}, the same cannot be said about func(int) and func(interface{}), because interfaces do not behave covariantly.
If type x implements interface ii, it doesn't mean that func(x) implements func(ii).
What you could do is pass func(int) into a function that expects interface{}, so you could do
package main
import "fmt"
func foo(x interface{}) {
fmt.Println("foo", x)
}
func add2(n int) int {
return n + 2
}
func main() {
foo(add2)
}
Because func(int)int does implement interface{}.
In addition to the Wikipedia link at the top of the answer, this post provides more details about the different kinds of variance programming languages support. It mostly uses other languages, because variance is best demonstrated with languages that support inheritance.

How can interfaces be comparable and at the same time functions not?

I have the following code-snippet:
type F func()
type I interface {}
func A() {}
func B() {}
func test() {
var a interface{} = A
var b interface{} = B
if A == B { // 1. Compile error
// Code
}
if a == b { // 2. No compile error
// Code
}
}
If functions are not comparable and interfaces are comparable, why can I assign a function to an interface type?
--
To clarify my question another code-snippet:
type I interface {
DoSomething()
}
type F func()
func (f F) DoSomething() {
f()
}
func A() {
fmt.Println("A")
}
func B() {
fmt.Println("B")
}
func test() {
var _a F = A
var _b F = B
var a I = _a
var b I = _b
if a == b { // 2. No compile error but panic
// Code
}
}
It seems to me, that I can break the type system with simple assignments.
I do not propose that functions should be comparable. My questions are:
Why interfaces are comparable by default?
Why is it not possible to mark an interface as comparable resp. not comparable?
Why is it not possible do define user defined-equality?
What is the motivation in this language design?
This is simply how the language is defined. From the spec:
Interface values are comparable. Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.
A comparison of two interface values with identical dynamic types causes a run-time panic if values of that type are not comparable.
function values are not comparable. However, as a special case, a [...] function value may be compared to the predeclared identifier nil.
That explains why the first if statement in your example fails at compile time, and why the second one fails at runtime.
To cite Ian Lance Taylor's message
from this thread on the Go mailing list:
On Wed, Nov 23, 2016 at 7:00 AM, T L wrote:
On Wednesday, November 23, 2016 at 10:35:59 PM UTC+8, Axel Wagner wrote:
So, your suggestion is, to have functions be comparable, but have the
comparisons always be false (unless compared to nil)? How would that be
useful and not completely confusing? e.g. how would that not lead to
people asking here, once a week, why (os.Open == os.Open) == false or
something like that?
No, I don't os.Open != os.Open, they are the same question, so they are
equal.
Even this seemingly simple statement is unclear. Go now supports
-buildmode=shared and -linkshared, meaning that a Go program can link against a set of shared libraries that are themselves written in Go.
When running in this mode, a function like os.Open can easily appear
multiple times in a single program image, in different shared
libraries. So while os.Open == os.Open might reasonably always be
true, given
func F() func(string) (*os.File, error) {
return os.Open
}
then it is much less clear whether
F() == os.Open
should be true, as F might be in a shared library and might return a
pointer to a different instance of os.Open.
And that's just one of the reasons.
See another one—regarding the function values which are closures
with the same code but closed over different variables—
explained in that same thread by Jesper Louis Andersen.
I would add that the whole thread is worth thorough reading and absorbing.

Golang struct calling embedded type methods when method has been overloaded

I am trying to learn Go, and I found a good resource here.
The example given on method overloading is reproduced below:
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Employee struct {
Human
company string
}
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
sam.SayHi()
}
Is it possible to call the "base" struct's (Human's) methods, eg. sam.Human.SayHi() Downcasting doesn't work (because there is no type hierarchy right?)
You can access the embedded struct of a parent struct by calling the member of the parent with the name of the embedded type's name. That's a mouthful, so it's probably easier to demonstrate it.
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
sam.SayHi() // calls Employee.SayHi
sam.Human.SayHi() // calls Human.SayHi
Outputs
Hi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX
Hi, I am Sam you can call me on 111-888-XXXX
This is the nearest approximation to sane polymorphism with both plain and pure virtual functions that I have found thus far. By the very nature of Go's design and the goal at hand, it is ugly but effective.
package main
import (
"fmt"
)
type I interface {
foo(s string) // Our "pure virtual" function
bar()
}
type A struct {i I}
type B struct {A}
type C struct {B}
// fk receivers, this is a "member function" so I'll use OO nomenclature
func (this *A) init(i I) {
this.i = i // the i contains (internal) pointers to both an object and a type
}
func (this *A) bar() {
this.i.foo("world")
}
func (this *B) foo(s string) {
fmt.Printf("hello %s\n", s)
}
func (this *C) foo(s string) {
fmt.Printf("goodbye cruel %s\n", s)
}
func main() {
var i I
b := &B{}
b.init(b) // passing b as the parameter implicitly casts it to an I interface object
b.bar()
c := &C{}
c.init(c)
c.bar() // c is a pointer to C, so Golang calls the correct receiver
i = b
i.bar()
i = c
i.bar() // Internally, i contains pointers to the C object and the C type,
// so that the correct receiver is called
}
https://play.golang.org/p/4qBfmJgyuHC
In real OO languages, each object of a class with any virtual functions must have a pointer to a virtual function table or a least type that maps to it. So adding an interface member to the base (embedded) struct only wastes an additional machine word for the pointer that will just point to its self.
Alternatively, we could remove the I interface member from A and the have pure virtual member function just accept the implementation as an argument.
type I interface {
foo(s string)
bar(i I)
}
type A struct {}
type B struct {A}
type C struct {B}
func (this *A) bar(i I) {
i.foo("world")
}
https://play.golang.org/p/9gvaCuqmHS8
But at this point, foo is no longer a pure virtual function, API users could pass any value whose type implements I, and the whole OO concept is broken. The object pointer portion of the I interface passed to bar doesn't need to be the same as this, but then again we didn't need to pass that same value using an init() function, but at least only an API user in the same package would be allowed to set it.
At this point, we have transitioned to the Go way of doing things: compositional programming with dependency injection. This is what Ken Thompson and the other designers thought was a better way to go -- at least for their stated goals. While it is vastly inferior in MANY respects, it does create many advantages and I won't argue those points that here.

Resources