I was exploring struct and interface and came across an interesting issue where I’ve declared a function which receives a pointer to the interface. I’m not able to call this function either with the value of struct or pointer to struct. Have a look at the following code snippet,
package main
type Intr interface {
m1()
}
type Student struct {
}
func (s *Student) m1() {
}
func main() {
s := Student{}
p := &Student{}
myfnc(s) // Not working
myfnc(p) // Not working
myfnc(p.(*Intr)) // Not working
myfnc(s.(*Intr)) // Not working
}
func myfnc(i *Intr) {
}
So if you look at the main function, we tried passing,
struct value
struct pointer
casting struct pointer to pointer to interface
casting struct value to pointer to interface
but none of them worked. I was curious to know when such a type of declaration will be required and how to use it.
My friend wants to ask that pointer to Interface is allowed in go as a param. How would we use that function because none of them work syntactically. Is it a bug?
Hi, @Prithvipal_Singh, There are two classifications of types in Go: concrete types and interface types. Concrete types are everything that is not an interface, including ints, strings, arrays, slices, maps and pointers. The empty interface type, interface{}, is an interface but a pointer to the empty interface, *interface{} is itself a concrete type, just like a slice of empty interfaces, []interface{} is a concrete type.
I am exploring interfaces, methods, and pointers in details. By curiosity, I tried to create a pointer to the interface. The go compiler did not complain, it allowed me to create it.
Since interfaces are a just contract which may have a list of methods. Any type which defines those methods, implicitly implements the interface. So I tried the above scenario. Thanks to you, you explained very well that pointer to an interface is also a concrete type.
But I still could not understand that what is the need for the pointer to interface? Why would anyone create a pointer to interface? What is the actual use case of it?
@Prithvipal_Singh the scenarios would have to be very specific, just like whatever sort of mind-boggling scenario would lead a developer to use a ***bool.
One somewhat real scenario I can think of is unmarshaling:
import (
"encoding/binary"
"reflect"
)
var (
endianness = binary.BigEndian
)
func MyUnmarshal(p []byte, t interface{}) error {
switch t := t.(type) {
case *uint32:
*t = endianness.Uint32(p[:4])
case *uint64:
*t = endianness.Uint64(p[:8])
// ...
case *interface{}:
// use the first 4 bytes of p to determine some magic type code
// and unmarshal into that:
code := endianness.Uint32(p[:4])
tp := getReflectTypeForCode(code)
v := reflect.New(tp).Interface()
if err := MyUnmarshal(p[4:], v); err != nil {
return err
}
*t = v
}
return nil
}