Golang: Where is an Interface method called? - go

I don't understand at which point an Interface method is being called. I'm looking at the following example from the Go Tour:
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (p Person) String() string {
return fmt.Sprintf("%v (%v years)", p.Name, p.Age)
}
func main() {
a := Person{"Arthur Dent", 42}
z := Person{"Zaphod Beeblebrox", 9001}
fmt.Println(a, z)
}
Problem:
I understand that the func (p Person) receives the String() method and that it returns the string I want to display. But the fmt.Println in the main() method has to call String() at some point, right?
I had a look at the source of fmt in godoc, but I still cannot figure it out!
Another example:
If I add my own interface, lets say Stringer2 with a method called String2() and then create a func (p Person) String2() {....}.
How does String() get executed by fmt.Println, but String2() not?

The value is passed to Println as an interface{}, and is checked if it satisfies the fmt.Stringer interface via a "type assertion" often in the form of a "type switch".
func IsStringer(i interface{}) {
switch s := i.(type) {
case fmt.Stringer:
fmt.Println("Person a has a String() method")
fmt.Println(s.String())
default:
fmt.Println("not a stringer")
}
// OR for a single type
if s, ok := i.(fmt.Stringer); ok {
fmt.Println("Person a has a String() method")
fmt.Println(s.String())
}
}
However, other methods may take precedence when printing from the fmt package. There are first checks for fmt.Formatter, fmt.GoStringer, error, and then finally fmt.Stringer.

The fmt package works with the interfaces it defines, in this case Stringer. It does not know of interfaces defined by you so it wouldn't know to call String2() even if you pass it a type that meets the Stringer2 interface.
Interfaces are a way to have common behavior between types. So if you create a function Foo(s Stringer2), Foo can simply call s.String2() confident that anything passed into it will have the function String2().
To go a bit deeper, fmt.Println takes interface{} types and then uses reflection to check if the given argument meets the Stringer interface to then call String().
Make sense?

Related

Passing an arbitrary function as a parameter in Go

I'm trying to expand my knowledge of Go's function pointers, and I have a question about what is and is not possible with passing functions as parameters in Go.
Let's say that I want to write a decorator() function that can wrap any existing function. For simplicity, let's limit this to functions that accept exactly one parameter and return exactly one value.
If I write a decorator that accepts func(interface{}) interface{} as it's argument, it will implicitly work as long as that function I pass in also accepts/returns an interface{} type (see funcA).
My question is--is there a way to convert an existing function of type func(string) string to a type of func(interface{}) interface{} so that it can also be passed into a decorator function without just wrapping it in a new anonymous function (see funcB)?
package main
import (
"fmt"
)
func decorate(inner func(interface{}) interface{}, args interface{}) interface {} {
fmt.Println("Before inner")
result := inner(args)
fmt.Println("After inner")
return result
}
func funcA(arg interface{}) interface{} {
fmt.Print("Inside A, with arg: ")
fmt.Println(arg)
return "This is A's return value"
}
func funcB(arg string) string {
fmt.Print("Inside B, with arg: ")
fmt.Println(arg)
return "This is B's return value"
}
func main() {
// This one works. Output is:
//
// Before inner
// Inside A, with arg: (This is A's argument)
// After inner
// This is A's return value
//
fmt.Println(decorate(funcA, "(This is A's argument)"))
// This doesn't work. But can it?
//fmt.Println(decorate(funcB, "(This is B's argument)"))
}
This is not possible. One reason for that is the mechanics of passing parameters differ from function to function, and using an interface{} arg does not mean "accept anything". For example, a function taking a struct as an arg will receive each member of that struct, but a function taking an interface{} containing that struct will receive two words, one containing the type of the struct, and the other containing a pointer to it.
So, without using generics, the only way to implement this is by using an adapter function.
Use the reflect package to handle functions with arbitrary argument and result types.
func decorate(inner interface{}, args interface{}) interface{} {
fmt.Println("Before inner")
result := reflect.ValueOf(inner).Call([]reflect.Value{reflect.ValueOf(args)})
fmt.Println("After inner")
return result[0].Interface()
}
Run the code on the playground.
Like the decorate function in the question, the function in this answer assumes one argument and one result. The function must be modified to handle other function types.
The OP should consider the tradeoffs between the anonymous wrapper function proposed in the question and the use of the reflect package here. Calling the function through the reflect API is slower than calling the function through the anonymous wrapper. There's also a loss of type safety with the reflect API. The anonymous wrapper function adds verbosity.
For the record, with Go 1.18 and the introduction of generics, the decorator function becomes almost trivial.
You may declare a type constraint as such:
type UnaryFunc[T any] interface {
func(T) T
}
The constraint itself is parametrized with T to allow for unary functions that take and return arbitrary types.
In the decorate function you then instantiate the constraint with a type parameter. The signature becomes:
decorate[T any, F UnaryFunc[T]](inner F, arg T) T
Thanks to type inference, you can just pass concrete arguments to the function, and both T and F will be unambiguous.
Example alternatives without a named constraint:
// accept and return T
decorate[T any](inner func(T) T, arg T) T
// only return T
decorate[T any](inner func() T) T
// return T and error
decorate[T any](inner func(T) (T, error), arg T) (T, error)
// N-ary function
decorate[T, U any](inner func(T, U) (T, error), argt T, argu U) (T, error)
The obvious limitation is that the interface constraint UnaryFunc specifies only functions that take and return exactly one arg of type T. You can't do otherwise, because the type set of an interface constraint may include types which support the same operations — and calling with one arg is not compatible with calling with N args.
The full program:
package main
import (
"fmt"
)
type UnaryFunc[T any] interface {
func(T) T
}
func decorate[T any, F UnaryFunc[T]](inner F, arg T) T {
fmt.Println("before inner")
result := inner(arg)
fmt.Println("after inner")
return result
}
func funcA(arg int) int {
fmt.Println("inside A with:", arg)
return arg
}
func funcB(arg string) string {
fmt.Println("inside B with:", arg)
return arg
}
func main() {
// this works
decorate(funcA, 200)
// this also works
decorate(funcB, "Func B")
}
Playground: https://go.dev/play/p/3q01NiiWsve
is there a way to convert an existing function of type func(string) string to a type of func(interface{}) interface{} so that it can also be passed into a decorator function without just wrapping it in a new anonymous function (see funcB)?
No. It's that simple: No.

Empty Interfaces in Golang

Edit: This is not the right way to use interfaces in Go. The purpose of this question is for me to understand how empty interfaces work in Go.
If all types in Go implement interface{} (empty interface), why can't I access the name field in the Cat and Dog structs? How can I get access to the name field of each struct through the function sayHi()?
package main
import (
"fmt"
)
func sayHi(i interface{}) {
fmt.Println(i, "says hello")
// Not understanding this error message
fmt.Println(i.name) // i.name undefined (type interface {} is interface with no methods)
}
type Dog struct{
name string
}
type Cat struct{
name string
}
func main() {
d := Dog{"Sparky"}
c := Cat{"Garfield"}
sayHi(d) // {Sparky} says hello
sayHi(c) // {Garfield} says hello
}
An interface{} is a method set, not a field set. A type implements an interface if it's methods include the methods of that interface. Since empty interface doesn't have any methods, all types implement it.
If you need to access a field, you have to get the original type:
name, ok:=i.(Dog).name
This will recover the name if i is a Dog.
Alternatively, implement a getName() function for both Dog and Cat, and then they will both implement the following interface:
type NamedType interface {
getName() string
}
Then you can rewrite your function as:
func sayHi(i NamedType) {
fmt.Println(i.getName())
}
You can't do that because interface values don't do that.
What interface values do—regardless of the interface type itself; it doesn't matter if the interface type is empty or not—is that they hold two things:
the concrete type of some value (or no type); and
the value of that concrete type (or no value).
So if some variable v or expression e has type I where I is an interface type, then you can, with some syntax, inspect either or both of these two "fields". They're not struct fields so you can't just use v.type, but you can do this:
switch v.(type) {
case int: // the value in v has type int
case *float64: // the value in v has type float64
// etc
}
The .(type) in a switch means let me look at the type field.
Getting the actual value is harder, because Go more or less requires that you check the type first. In your case, you know that i holds either a Dog or a Cat, so you can write:
var name string
switch i.(type) {
case Dog: name = i.(Dog).name
case Cat: name = i.(Cat).name
default: panic("whatever 'i' is, it is not a Dog or Cat")
}
fmt.Println(name)
This is pretty clumsy, and there are lots of ways to make it less clumsy, but that's always the first step: figure out what the type is.
Well, sometimes there's a step before the first step: figure out whether the variable has anything at all in it. You do this with:
if i == nil {
...
}
Note, however, that if i has some typed value in it, and the type can hold nil pointers, the value part of i can be nil and yet i == nil will be false. That's because i does have a type in it.
var i interface{}
var p *int
if i == nil {
fmt.Println("i is initially nil")
}
if p == nil {
fmt.Println("p is nil")
}
i = p
if i != nil {
fmt.Printf("i is now not nil, even though i.(*int) is %v\n", i.(*int))
}
(try this on the Go playground).
This usually isn't the right way to use interface
Most often—there are exceptions—we don't even try to look at the type of some interface. Instead, we define an interface that provides methods—functions we can call—that do something we need done. See Burak Serdar's answer in which the interface type has a getName method. Then, instead of trying to figure out which of some limited set of types someone gave us, we just say:
name := i.getName()
to invoke the getName method on the underlying concrete value. If i holds a Dog, that calls func (Dog) getName() string, which you'll need to define. If i holds a Cat, it calls func (Cat) getName() string. If you decide to add to your collection a type named Bird, you can define func (Bird) getName() string, and so on.
(Usually, the methods would be exported too: GetName, rather than getName.)
Like you say, interface{} is an empty interface. How can you assume that something "empty" has a name field in it (fmt.Println(i.name))? You can't. In fact, go doesn't support fields in interfaces, only methods.
What you can do (and there are, of course, many solutions), is to define an interface (let's call it Pet) which has a method returning the pet's name:
type Pet interface {
getName() string
}
Then you can receive this interface (its object) in the sayHi function and use it to print the pet's name:
func sayHi(i Pet) {
fmt.Println(i.getName())
}
Now, in order to be able to pass Dog or Cat to sayHi(), both of these structs have to implement the interface. So, define the getName() methods for them:
func (d Dog) getName() string {
return d.name
}
func (c Cat) getName() string {
return c.name
}
And that's it.
It can also be implemented using switch type as below-
package main
import (
"fmt"
)
func sayHi(i interface{}) {
fmt.Println(i, "says hello")
switch x := i.(type) {
case Dog:
fmt.Println(x.name)
case Cat:
fmt.Println(x.name)
}
}
type Dog struct {
name string
}
type Cat struct {
name string
}
func main() {
d := Dog{"Sparky"}
c := Cat{"Garfield"}
sayHi(d) // {Sparky} says hello
sayHi(c) // {Garfield} says hello
}
Playground link - https://go.dev/play/p/p4s3_jmmbGJ

How HandlerFunc(f) convert a function to an interface type?

When check following code, got a doubt with type convert from function to interface.
Code
http_hello.go:
package main
import (
"fmt"
"log"
"net/http"
)
// hello http,
func helloHttp() {
// register handler,
http.Handle("/", http.HandlerFunc(helloHandler))
// start server,
err := http.ListenAndServe(":9090", nil)
if err != nil {
log.Fatal("ListenAndServe:", err)
}
}
// handler function - hello,
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path)
}
func main() {
helloHttp()
}
The above code works.
(Then I tried to write a small program to check is this a general feature, but it won't work, check following code)
func_to_intf.go:
package main
import (
"fmt"
)
// an interface,
type Adder interface {
add(a, b int) int
}
// alias of a function signature,
type AdderFunc func(int, int) int
// a simple add function,
func simpleAdd(a, b int) int {
return a + b
}
// call Adder interface to perform add,
func doAdd(a, b int, f Adder) int {
return f.add(a, b)
}
func funcToIntf() {
fa := AdderFunc(simpleAdd)
fmt.Printf("%#v, type: %T\n", fa, fa)
a, b := 1, 2
sum := doAdd(a, b, fa)
fmt.Printf("%d + %d = %d\n", a, b, sum)
}
func main() {
funcToIntf()
}
Output:
./func_to_intf.go:30:14: cannot use fa (type AdderFunc) as type Adder
in argument to doAdd: AdderFunc does not implement Adder (missing add
method)
Questions
http.HandlerFunc(helloHandler) get a value of type http.Handler, since that's what http.Handle() expect, is that correct?
If yes, then means it convert a function into a value of an interface type, how did that happen?
Is this a built-in feature of go?
I did a test (as in func_to_intf.go above), and seems not.
Or, is http.HandlerFunc's special implementation achieve that?
#Update - Summary
(Though the answer(s) addressed the questions pretty well, but after reviewing & more testing, there are several other go features required to totally erase the original doubt, as following.)
Function type.
Function is value, and it has type.
Function type could be defined via type keyword on a function signature.
e.g type AdderFunc func(int, int) int
Type convertor T(v) on function.
Any function could be converted to a function type with the same signature, just via T(v), use function type name as T, and actual function as v.
Then when the new value is called, the actual function v is called.
e.g fa := AdderFunc(simpleAdd)
(this is blur to me before asking the question, and that's one of the main reason I was confused).
It is a simple type-conversion.
In Go you can define custom type besides structs. In this case, http.HandlerFunc is a function type, func(http.ResponseWriter,*http.Request). Since your function is of the same underlying type (signature) as the custom type, it can be converted to it.
Furthermore, code can define methods on custom type, no matter what underlying type it is, or whether it is a struct or not. In this case, http package defines ServeHTTP method on it, and of course, it just calls the function itself.
You can read the source code here: https://golang.org/src/net/http/server.go?s=58384:58444#L1936
As for the adder in your sample code, you can do the same: Define a method on AdderFunc.
func (a AdderFunc) add(x, y int) int {
return a(x, y)
}
Playground: https://play.golang.org/p/5mf_afHLQA2
http.HandlerFunc is a type that satisfy interface http.Handler by providing method http.ServeHTTP(ResponseWriter, *Request).
http.HandlerFunc(helloHandler) is a type conversion which convert types with same underlying base type but different method set.
You example working
Not special or built-in feature. Instead http.HandlerFunc is a type that implements the http.Handler interface. Have a look at its implementation which is quite nifty https://github.com/golang/go/blob/d3c3aaa61f7598f275f30fabd3749379fe0f2720/src/net/http/server.go#L1956
As the docs say:
The HandlerFunc type is an adapter to allow the use of ordinary functions as HTTP handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler that calls f.
So, it's not a function, but a wrapper type, declared as:
type HandlerFunc func(ResponseWriter, *Request)
But Go allows (and that's one of its greatest features, in my opinion) to make any newly declared type implement any possible interface just by defining the require method. So the type HandlerFunc implements the interface Handler by defining the method ServeHttp. The implementation just calls the wrapped function.

Why does switch match a different type in below code sample in golang

Link:
https://play.golang.org/p/69I8PAuoAV
Extract:
package main
import "fmt"
type Stringer interface {
String() string
}
type fakeString struct {
content string
}
// function used to implement the Stringer interface
func (s *fakeString) String() string {
return s.content
}
func printString(value interface{}) {
switch str := value.(type) {
case string:
fmt.Println(str)
case Stringer:
fmt.Println(str.String())
}
}
func main() {
s := &fakeString{"Ceci n'est pas un string"}
printString(s)
printString("Hello, Gophers")
}
The printString(s) function call when reaching case matches the case Stringer part.
s is of type *fakeString not Stringer.
Why does it match Stringer.
I did a fmt.Println(reflect.TypeOf(str)) and it confirmed the type as *main.fakeString
In Go to satisfy an interface all you have to do is implement the methods of that interface nothing else. In this case to have a behavior as a Stringer you have to implement String() string, so the type fakeString behaves as a Stringer because implement that method; in terms of OOP we use interfaces just to define behavior not types or values. So you may be implementing Go interfaces all day without knowing, but not big deal, it only matters when you have to satisfy behaviors.
Actually in a real project you may want to add a default case to your switch in the method printString, to detect when the interface{} is something else, like this:
func printString(value interface{}) {
switch str := value.(type) {
case string:
fmt.Println("string", str)
case Stringer:
fmt.Println("Stringer", str.String())
default:
fmt.Printf("unexpected type: %T value: '%v'", str, str)
}
}
// main:
printString(2)
https://play.golang.org/p/pmxSXfUu4e
This is interface satisfaction in golang.
There are two kinds of type in golang: interface type and concrete type.
concrete type works exactly as you expected in switch: the variable is an instance of the given type
interface type on the other hand works differently, it checks if the variable satisfies the interface.
Hum, safisfies? How does it work?
A (concrete) type satisfies an interface if it possesses all the methods the interface requires.
-- the golang programming language
In the case, Stringer is an interface, declaring only one method: String() string. And fakeString satisfies it by having its own String() string method.
Two things to note however:
concrete type can have many other methods, it still satisfies the interface if it possesses all methods declared in interface
the methods order does not matter, all that matters is the set of methods.

Golang methods with same name and arity, but different type

The following code works fine. Two methods operating on two different structs and printing a field of the struct:
type A struct {
Name string
}
type B struct {
Name string
}
func (a *A) Print() {
fmt.Println(a.Name)
}
func (b *B) Print() {
fmt.Println(b.Name)
}
func main() {
a := &A{"A"}
b := &B{"B"}
a.Print()
b.Print()
}
Shows the desired output in the console:
A
B
Now, if I change the method signature in the following way I get an compile error. I just move the receiver of the method to the arguments of the method:
func Print(a *A) {
fmt.Println(a.Name)
}
func Print(b *B) {
fmt.Println(b.Name)
}
func main() {
a := &A{"A"}
b := &B{"B"}
Print(a)
Print(b)
}
I can't even compile the program:
./test.go:22: Print redeclared in this block
previous declaration at ./test.go:18
./test.go:40: cannot use a (type *A) as type *B in function argument
Why is it that I can interchange struct types in the receiver, but not in the
arguments, when the methods have the same name and arity?
Because Go does not support overloading of user-defined functions on their argument types.
You can make functions with different names instead, or use methods if you want to "overload" on only one parameter (the receiver).
You can use type introspection. As a general rule, though, any use of the generic interface{} type should be avoided, unless you are writing a large generic framework.
That said, a couple of ways to skin the proverbial cat:
Both methods assume a Print() method is defined for both types (*A and *B)
Method 1:
func Print(any interface{}) {
switch v := any.(type) {
case *A:
v.Print()
case *B:
v.Print()
default:
fmt.Printf("Print() invoked with unsupported type: '%T' (expected *A or *B)\n", any)
return
}
}
Method 2:
type Printer interface {
Print()
}
func Print(any interface{}) {
// does the passed value honor the 'Printer' interface
if v, ok := any.(Printer); ok {
// yes - so Print()!
v.Print()
} else {
fmt.Printf("value of type %T passed has no Print() method.\n", any)
return
}
}
If it's undesirable to have a Print() method for each type, define targeted PrintA(*A) and PrintB(*B) functions and alter Method 1 like so:
case *A:
PrintA(v)
case *B:
PrintB(v)
Working playground example here.
You can not do function or method overloading in Go. You can have two methods with the same names in Go but the receiver of these methods must be of different types.
you can see more in this link .

Resources