How does I check if a type implement an interface?

9,215 views
Skip to first unread message

gnu.bash

unread,
Nov 16, 2010, 1:48:56 PM11/16/10
to golang-nuts
Hi,

example:

type iface interface {
bla()
}

type inty int

func (i *inty) bla() {
}

I need a something like

func CheckForInterface(object, interface) bool

thanks for help, aotto1968

jimt

unread,
Nov 16, 2010, 1:56:39 PM11/16/10
to golang-nuts
A type assertion will help:

if ok := inty.(iface); ok {
yay()

jimmy frasche

unread,
Nov 16, 2010, 1:59:48 PM11/16/10
to jimt, golang-nuts

Type assertions go the other way.

You could write a CheckForInterface function with the reflection
package, I suppose. But I don't see the utility.

chris dollin

unread,
Nov 16, 2010, 2:00:06 PM11/16/10
to gnu.bash, golang-nuts
On 16 November 2010 18:48, gnu.bash <aott...@t-online.de> wrote:
> Hi,
>
> example:
>
> type iface interface {
>    bla()
> }
>
> type inty int
>
> func (i *inty) bla() {
> }
>
> I need a something like
>
> func CheckForInterface(object, interface) bool

jimt has mentioned using type assertions, but I'd be interested
to know what you're trying to do with this check.

Chris

--
Chris "allusive" Dollin

gnu.bash

unread,
Nov 16, 2010, 2:13:30 PM11/16/10
to golang-nuts
My Example:

===========================================
package gomsgque
type IServerSetup interface {
ServerSetup() MqSException
}
===========================================
package main
type Server struct {
*gomsgque.MqS
}
func NewServer() *Server {
//fmt.Println("NewServer...")
ret := &Server{gomsgque.NewMqS()}
//ret.ConfigServerSetup()
return ret
}
func (this *Server) ServerSetup() gomsgque.MqSException {
var ret gomsgque.MqSException
return ret
}
func main() {
var srv = NewServer()
defer srv.Exit("END")
fmt.Println("val = ", reflect.Typeof(srv))
fmt.Println("val = ", Server.(gomsgque.IServerSetup))
}

=> server.go:45: type Server is not an expression

using the pointer object "srv"

func main() {
var srv = NewServer()
defer srv.Exit("END")
fmt.Println("val = ", reflect.Typeof(srv))
fmt.Println("val = ", srv.(gomsgque.IServerSetup))
}

=> server.go:45: invalid type assertion: srv.(gomsgque.IServerSetup)
(non-interface type *Server on left)

using the object "*srv"

func main() {
var srv = NewServer()
defer srv.Exit("END")
fmt.Println("val = ", reflect.Typeof(srv))
fmt.Println("val = ", (*srv).(gomsgque.IServerSetup))
}

=> server.go:45: invalid type assertion: *srv.(gomsgque.IServerSetup)
(non-interface type Server on left)


is an other option available ?

gnu.bash

unread,
Nov 16, 2010, 2:36:51 PM11/16/10
to golang-nuts
Hi,

I come from c++/java/c# and the behavior of an object changes
depending on the
interfaces implemented

example c++ =================================

void MqC::Init () {
...
// init the server interface
IServerSetup * const iSetup =
dynamic_cast<IServerSetup*const>(this);
if (iSetup != NULL) {
struct ProcCallS * ptr = (struct ProcCallS *)
MqSysMalloc(MQ_ERROR_PANIC, sizeof(*ptr));
ptr->type = ProcCallS::PC_IServerSetup;
ptr->call.ServerSetup = iSetup;
MqConfigSetServerSetup (&context, ProcCall,
static_cast<MQ_PTR>(ptr), ProcFree, NULL);
}
....

JAVA

JNIEXPORT void JNICALL NS(ContextCreate) (
JNIEnv *env,
jobject self
)
{
...
// check for Server
if ((*env)->IsInstanceOf(env, self, NS(Class_IServerSetup)) ==
JNI_TRUE) {
ErrorMqToJavaWithCheck (NS(ProcCreate)(context, self, NULL,
NS(MID_IServerSetup_ServerSetup), NULL, &call));
MqConfigSetServerSetup (context, NS(ProcCall), call, NS(ProcFree),
NS(ProcCopy));
}

C#

public MqS() {
...
if (this is IServerSetup) {
MqConfigSetServerSetup (context, fProcCall, (IntPtr)
GCHandle.Alloc(
new ProcData((Callback)((IServerSetup) this).ServerSetup)),
fProcFree, IntPtr.Zero);
}
...


mfg, Andreas Otto

chris dollin

unread,
Nov 16, 2010, 2:55:41 PM11/16/10
to gnu.bash, golang-nuts
On 16 November 2010 19:13, gnu.bash <aott...@t-online.de> wrote:

> is an other option available ?

What are you trying to /do/?

In:

<<<<<<<
func main() {
var srv = NewServer()
defer srv.Exit("END")
fmt.Println("val = ", reflect.Typeof(srv))
fmt.Println("val = ", (*srv).(gomsgque.IServerSetup))
}
>>>>>>>

you are trying to print out a type representation for srv.
(You could use %T, which would be a lot nicer than
doing the reflect by hand.) But you /know/ what the
type of srv is: it's the type returned by NewServer, which
is *Server.

You can't type-test a non-interface type but you can
an interface type; so try

fmt.Println("val = ", interface{}(srv).(gomsgque.IServerSetup))

The `interface{}(s)` is a cast of srv to the type interface{},
which you can now apply the type-check to.

chris dollin

unread,
Nov 16, 2010, 3:02:56 PM11/16/10
to gnu.bash, golang-nuts
On 16 November 2010 19:36, gnu.bash <aott...@t-online.de> wrote:
> Hi,
>
> I come from c++/java/c# and the behavior of an object changes
> depending on the
> interfaces implemented

Different interfaces expose different behaviours, yes.

> JAVA
>
> JNIEXPORT void JNICALL NS(ContextCreate) (
>  JNIEnv  *env,
>  jobject self
> )
> {
>  ...
>  // check for Server
>  if ((*env)->IsInstanceOf(env, self, NS(Class_IServerSetup)) ==
> JNI_TRUE) {
>    ErrorMqToJavaWithCheck (NS(ProcCreate)(context, self, NULL,
> NS(MID_IServerSetup_ServerSetup), NULL, &call));
>    MqConfigSetServerSetup (context, NS(ProcCall), call, NS(ProcFree),
> NS(ProcCopy));
>  }

That's not Java.

roger peppe

unread,
Nov 16, 2010, 3:13:14 PM11/16/10
to gnu.bash, golang-nuts
you can check whether a type implements an interface
by simply assigning to a variable of the required interface
type. the compiler will tell you if it does not implement the
interface.

On 16 November 2010 18:48, gnu.bash <aott...@t-online.de> wrote:

jimmy frasche

unread,
Nov 16, 2010, 3:15:42 PM11/16/10
to roger peppe, gnu.bash, golang-nuts
If you want to take an unknown object and do different things based on
its type, you can use a type switch.

Jessta

unread,
Nov 16, 2010, 11:53:07 PM11/16/10
to gnu.bash, golang-nuts
On Wed, Nov 17, 2010 at 5:48 AM, gnu.bash <aott...@t-online.de> wrote:
> I need a something like
>
> func CheckForInterface(object, interface) bool
>

There is no reason to need to know what interfaces a type satisfies at runtime.
You just make an interface for the behaviour your function requires
and the compiler will tell you if the types you're passing in satisfy
that interface.

- jessta

--
=====================
http://jessta.id.au

gnu.bash

unread,
Nov 17, 2010, 1:58:25 AM11/17/10
to golang-nuts
Hi,

the type print out is just for testing.
I want to bind an external library to GO and I use Interfaces
modify the behavior.
For example JAVA
final class Server extends MqS implements IServerSetup, ...... {
public void ServerSetup() throws MqSException {
....
}
}
during setup (using JNI) I check if the interface is available ...

JNIEXPORT void JNICALL NS(ContextCreate) (
JNIEnv *env,
jobject self
)
{
....
if ((*env)->IsInstanceOf(env, self, NS(Class_IServerSetup)) ==
JNI_TRUE) {
ErrorMqToJavaWithCheck (NS(ProcCreate)(context, self, NULL,
NS(MID_IServerSetup_ServerSetup), NULL, &call));
MqConfigSetServerSetup (context, NS(ProcCall), call, NS(ProcFree),
NS(ProcCopy));
}
...
}

and if YES is call my own C code to call this Interface function. In
this case the code behave as Server and
use the "ServerSetup" method to configure the server.

Every language supporting interfaces support a function like
"IsInstanceOf" in Java to check for the
availability of this interface

the Println code from down is just for testing

mfg, aotto1968



On 16 Nov., 20:55, chris dollin <ehog.he...@googlemail.com> wrote:

gnu.bash

unread,
Nov 17, 2010, 2:21:19 AM11/17/10
to golang-nuts
Hi,

this is JNI, I post a full JAVA example above

andrey mirtchovski

unread,
Nov 17, 2010, 2:24:36 AM11/17/10
to gnu.bash, golang-nuts
that is an impressive example, I must admit.
MID_IServerSetup_ServerSetup just blows my mind!

chris dollin

unread,
Nov 17, 2010, 2:48:52 AM11/17/10
to gnu.bash, golang-nuts
On 17 November 2010 06:58, gnu.bash <aott...@t-online.de> wrote:

> Every language supporting interfaces support a function like
> "IsInstanceOf" in Java to check for the
> availability of this interface

And indeed you can do this in Go, as the message from me you quoted:

>> You can't type-test a non-interface type but you can
>> an interface type; so try
>>
>>  fmt.Println("val = ", interface{}(srv).(gomsgque.IServerSetup))
>>
>> The `interface{}(s)` is a cast of srv to the type interface{},
>> which you can now apply the type-check to.

points out.

gnu.bash

unread,
Nov 17, 2010, 2:50:52 AM11/17/10
to golang-nuts
Hi,

I found a temporary solution

1. gomsgque =====================================
type IServerSetup interface { ServerSetup() MqSException }
type IServerCleanup interface { ServerCleanup() MqSException }

func (this *MqS) ConfigSetServerSetup(ifc IServerSetup) {
C.MqConfigSetServerSetup(this.ctx, nil, nil, nil, nil)
}

func (this *MqS) ConfigSetServerCleanup(ifc IServerCleanup) {
C.MqConfigSetServerCleanup(this.ctx, nil, nil, nil, nil)
}
2. main =========================================
type Server struct {
*gomsgque.MqS
}

func NewServer() *Server {
fmt.Println("NewServer...")
ret := &Server{gomsgque.NewMqS()}
ret.ConfigSetServerSetup(ret)
ret.ConfigSetServerCleanup(ret)
//ret.ConfigServerSetup()
return ret
}

// //export ServerSetup
func (this *Server) ServerSetup() gomsgque.MqSException {
var ret gomsgque.MqSException
return ret
}

func main() {
var srv = NewServer()
defer srv.Exit("END")

fmt.Printf("val = %T\n", srv)
}

the compiler *complain* about missing interface "ServerCleanup"
but you still have the "double (ret)" coding...

ret.ConfigSetServerSetup(ret)

The problem is the "embedded" object "MqS"

the first "ret" will be the "MqS->this" and the second "ret" will be
the "Server->this"


mfg, Andreas Otto (aotto1968)

gnu.bash

unread,
Nov 17, 2010, 3:02:12 AM11/17/10
to golang-nuts
Hi,

I do the following check ....


func main() {
var srv = NewServer()
defer srv.Exit("END")

fmt.Printf("val = %T\n", srv)
fmt.Println("val = ", interface{}(srv).(gomsgque.IServerSetup))
fmt.Println("val = ", interface{}(srv).(gomsgque.IServerCleanup))
}

IServerSetup is "implemented" and IServerCleanup is *not*
"implemented"

and this is the solution ....
> ./server
NewServer...
val = *main.Server
val = &{0x7f47dd97f0f0}

the code stops after the first println

mfg, andreas otto

chris dollin

unread,
Nov 17, 2010, 3:22:38 AM11/17/10
to gnu.bash, golang-nuts

My mistake.

What I should have added was that to /test/ whether some interface
value V can be used as some type T, you need to use a type-testing
assignment (or declaration):

someT, isT := V.(T)

[or its big brother, the type switch)]

which will set isT to true if V can work as a T and someT to the T-shaped
value for V.

Using V.(T) as a single expression will deliver the T-value of V if
possible but otherwise panic.

jimmy frasche

unread,
Nov 17, 2010, 3:27:14 AM11/17/10
to chris dollin, gnu.bash, golang-nuts
func setup(x interface{}) MqSException {
if s, ok := x.(ServerSetup); ok {
return s.ServerSetup()
}
return nil
}

and similiarly for the cleanup. Do not prepend an I to your interface names.

gnu.bash

unread,
Nov 17, 2010, 3:47:51 AM11/17/10
to golang-nuts
Hi,

now the "inline" test is working as well ....

func main() {
var srv = NewServer()
defer srv.Exit("END")

fmt.Printf("val = %T\n", srv)
if s, ok := interface{}(srv).(gomsgque.IServerSetup); ok {
fmt.Printf("val = has gomsgque.IServerSetup -> %T\n", s)
}
if s, ok := interface{}(srv).(gomsgque.IServerCleanup); ok {
fmt.Printf("val = has gomsgque.IServerCleanup -> %T\n", s)
}

fmt.Println("END")
}

wit the result ....

NewServer...
val = *main.Server
val = has gomsgque.IServerSetup -> *main.Server
END

=> this is right .... well done

some thing left over .... if I use the code ...
func main() {
var srv = NewServer()
defer srv.Exit("END")

fmt.Printf("val = %T\n", srv)
if s, ok := interface{}(srv).(gomsgque.IServerSetup); ok {
fmt.Printf("val = has gomsgque.IServerSetup -> \n")
}
if s, ok := interface{}(srv).(gomsgque.IServerCleanup); ok {
fmt.Printf("val = has gomsgque.IServerCleanup -> \n")
}

fmt.Println("END")
}

... without reusing the variable "s" ... i get an compiler error ...

server.go:47: s declared and not used
server.go:50: s declared and not used
make: *** [server] Fehler 1

... to solve this I have to use the "_" dummy variable ....

thanks to everybody ....

mfg, Andreas Otto

Reply all
Reply to author
Forward
0 new messages