apache / dubbo-go

Go Implementation For Apache Dubbo .
https://dubbo.apache.org/
Apache License 2.0
4.71k stars 925 forks source link

Ftr: support java generic #48

Closed Sharember closed 4 years ago

Sharember commented 5 years ago

go-for-apache-dubbo hessian2 doesn't support generics yet,like Response<T>

test case:

com.ikurento.user.Response<T> 

Responst<Integer> com.ikurento.user.UserProvider.sum(int a, int b)
type Response struct {
    OK int32
    ERR int32
    Status int32
    Err string
        // How do I define this field
    Data interface{}
}

func (Response) JavaClassName() string {
    return "com.ikurento.user.Response"
}

func (r Response) String() string {
    return fmt.Sprintf(
        "Response{OK:%d, ERR:%d, Status:%d, Err:%s, Data:%s}",
        r.OK, r.ERR,r.Status,r.Err,r.Data,
    )
}

hessian.RegisterPOJO(&Response{})

response := &Response{}
err := conMap["com.ikurento.user.UserProvider"].GetRPCService().(*UserProvider).Sum(context.TODO(), []interface{}{1, 2}, response)
jilliss commented 5 years ago

I think this request is not reasonable. Because golang does not support generics only supports empty interfaces(interface{}). The generics of java are just automatic type conversions by jvm,and the compile-time type is uniformly erased to Object.

Golang either returns the determined type or returns an empty interface. An empty interface can also be considered a deterministic type

So

In summary, I think that implementing this function is too expensive. the caller should know the type of the return value of the service that he is calling.Even if you don't know, golang also provides a reflection package (reflect) to determine the unknown type.

java code

public class JavaClass<V> {

    private V verification(V a) {
        System.out.println(a.getClass());
        return a;
    }
    private void test() {
        JavaClass<Integer> integerJavaTest = new JavaClass<>();
        integerJavaTest.verification(1);
    }
}

java byte code

// class version 52.0 (52)
// access flags 0x21
// signature <V:Ljava/lang/Object;>Ljava/lang/Object;
// declaration: com/boot/security/server/JavaClass<V>
public class com/boot/security/server/JavaClass {

  // compiled from: JavaClass.java

  // access flags 0x1
  public <init>()V
   L0
    LINENUMBER 7 L0
    ALOAD 0
    INVOKESPECIAL java/lang/Object.<init> ()V
    RETURN
   L1
    LOCALVARIABLE this Lcom/boot/security/server/JavaClass; L0 L1 0
    // signature Lcom/boot/security/server/JavaClass<TV;>;
    // declaration: this extends com.boot.security.server.JavaClass<V>
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 0x2
  // signature (TV;)TV;
  // declaration: V verification(V)
  private verification(Ljava/lang/Object;)Ljava/lang/Object;
    // parameter  a
   L0
    LINENUMBER 11 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 1
    INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class;
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L1
    LINENUMBER 12 L1
    ALOAD 1
    ARETURN
   L2
    LOCALVARIABLE this Lcom/boot/security/server/JavaClass; L0 L2 0
    // signature Lcom/boot/security/server/JavaClass<TV;>;
    // declaration: this extends com.boot.security.server.JavaClass<V>
    LOCALVARIABLE a Ljava/lang/Object; L0 L2 1
    // signature TV;
    // declaration: a extends V
    MAXSTACK = 2
    MAXLOCALS = 2

  // access flags 0x2
  private test()V
   L0
    LINENUMBER 17 L0
    NEW com/boot/security/server/JavaClass
    DUP
    INVOKESPECIAL com/boot/security/server/JavaClass.<init> ()V
    ASTORE 1
   L1
    LINENUMBER 18 L1
    ALOAD 1
    ICONST_1
    INVOKESTATIC java/lang/Integer.valueOf (I)Ljava/lang/Integer;
    INVOKESPECIAL com/boot/security/server/JavaClass.verification (Ljava/lang/Object;)Ljava/lang/Object;
    POP
   L2
    LINENUMBER 19 L2
    RETURN
   L3
    LOCALVARIABLE this Lcom/boot/security/server/JavaClass; L0 L3 0
    // signature Lcom/boot/security/server/JavaClass<TV;>;
    // declaration: this extends com.boot.security.server.JavaClass<V>
    LOCALVARIABLE integerJavaTest Lcom/boot/security/server/JavaClass; L1 L3 1
    // signature Lcom/boot/security/server/JavaClass<Ljava/lang/Integer;>;
    // declaration: integerJavaTest extends com.boot.security.server.JavaClass<java.lang.Integer>
    MAXSTACK = 2
    MAXLOCALS = 2
}

You can see that the java type is erased and the method signature is Object.