I\'ve read \"Effective Go\" and other Q&As like this: golang interface compliance compile type check , but nonetheless I can\'t understand properly how to use this techn
Following will work:
val:=MyType("hello")
var i interface{}=val
v, ok:=i.(Somether)
It is also possible to use Implements(u Type) bool
method of reflect.Type
in the following way:
package main
import (
"reflect"
)
type Somether interface {
Method() bool
}
type MyType string
func (mt MyType) Method() bool {
return true
}
func main() {
inter := reflect.TypeOf((*Somether)(nil)).Elem()
if reflect.TypeOf(MyType("")).Implements(inter) {
print("implements")
} else {
print("doesn't")
}
}
You can read more on that in the documentation.
You only have to check if a value implements an interface if you don't know the value's type. If the type is known, that check is automatically done by the compiler.
If you really want to check anyways, you can do it with the second method you gave:
var _ Somether = (*MyType)(nil)
which would error at compile time:
prog.go:23: cannot use (*MyType)(nil) (type *MyType) as type Somether in assignment:
*MyType does not implement Somether (missing Method method)
[process exited with non-zero status]
What you are doing here, is assigning a pointer of MyType
type (and nil
value) to a variable of type Somether
, but since the variable name is _
it is disregarded.
If MyType
implemented Somether
, it would compile and do nothing
You can also take Alpha's solution:
val := MyType("hello")
var i interface{} = val
v, ok := i.(Somether)
... and reduce it further:
val := MyType("hello")
v, ok := interface{}(val).(Somether)
If you're trying to test for one-off methods, you can even do something like:
val := MyType("hello")
v, ok := interface{}(val).(interface {
Method() bool
})
NOTE: Make sure you are very careful with "pointer receiver" versus "value receiver" implementations. If the implementation uses a pointer the assertion will fail when passing in a value object. If the implementation uses a value receiver, both assertions will pass.
// Implement Somether as a POINTER receiver method
func (mt *MyType) Method() bool {
return true
}
func main() {
val := MyType("hello")
v, ok := interface{}(val).(Somether)
fmt.Println(v, ok)
// Output: <nil> false
// Notice the pass by reference
v, ok := interface{}(&val).(Somether)
fmt.Println(v, ok)
// Output: 0xc000010200 true
}
versus
// Implement Somether as a VALUE receiver method
func (mt MyType) Method() bool {
return true
}
func main() {
val := MyType("hello")
v, ok := interface{}(val).(Somether)
fmt.Println(v, ok)
// Output: hello true
// Notice the pass by reference
v, ok := interface{}(&val).(Somether)
fmt.Println(v, ok)
// Output: 0xc00008e1e0 true
}