fix(generic): support variadic method invocation via generic call#3284
fix(generic): support variadic method invocation via generic call#3284mochengqian wants to merge 2 commits intoapache:developfrom
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #3284 +/- ##
===========================================
+ Coverage 46.76% 49.68% +2.91%
===========================================
Files 295 469 +174
Lines 17172 34841 +17669
===========================================
+ Hits 8031 17310 +9279
- Misses 8287 16124 +7837
- Partials 854 1407 +553 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
AlexStocks
left a comment
There was a problem hiding this comment.
Additional code review
AlexStocks
left a comment
There was a problem hiding this comment.
Additional suggestions
|
Please attention that your PR target branch should be develop. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR fixes generic ($invoke) calls from Java into Go methods with variadic parameters (...T) by reshaping generic args into a typed slice and invoking the target method using reflect.CallSlice when appropriate, preventing reflect.Value.Call panics (issue #3259).
Changes:
- Expose variadic metadata via
MethodType.IsVariadic(). - Update generic service filter to validate variadic arg counts and reshape trailing args into the correct typed slice.
- Update proxy invocation to prefer variadic handling and use
CallSlicewhen the final argument is already a slice.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| common/rpc_service.go | Adds IsVariadic() to expose variadic method info. |
| filter/generic/service_filter.go | Validates variadic arg counts and reshapes variadic args into typed slices for invocation. |
| proxy/proxy_factory/utils.go | Uses CallSlice for pre-packed variadic slices to avoid reflection panics. |
| proxy/proxy_factory/default.go | Ensures variadic branch runs before []interface{} passthrough logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dd65da7 to
06bbd4e
Compare
|



Description
Fixes issue #3259
注意:本次PR为短期方案,但是已经可以关闭issue #3259
背景
Java 客户端通过泛化调用(
$invoke)访问 Go 服务端定义了变长参数(...T)的方法时,框架会触发
reflect.Value.Callpanic,导致调用 100% 失败(测试见issue的comment)。根因
两层问题叠加:
service_filter.go参数数量校验过严 —argsType中变长参数被记录为单个切片类型(如
[]string),但 Java 端可能以离散形式发送多个 args,len(args) != len(argsType)直接拒绝callLocalMethod使用reflect.Value.Call()— 即使参数数量对齐,已打包为切片的变长参数传入
Call()时会因类型不匹配触发panic: cannot use []string as type string in Call修复方案
采用统一数组传参 + CallSlice 动态类型重塑策略,改动封锁在框架内部,
对外部业务代码零侵入:
common/rpc_service.goMethodType新增IsVariadic()方法,暴露变长方法元信息filter/generic/service_filter.goreflect.MakeSlice重塑为精确类型切片proxy/proxy_factory/utils.goCallSlice替代Callproxy/proxy_factory/default.go[]interface{}passthrough 检测,避免...interface{}被错误多包一层支持 Java 端两种传参形式:
args: ["a", "b"]— 框架自动收拢为切片args: [["a", "b"]]— 框架自动解包内层数组用户现在怎么调用:
Java 泛化调用 Go variadic 方法,两种传参方式都支持了:
方式 A:离散传参
genericService.$invoke(
"MultiArgs",
new String[]{"java.lang.String", "java.lang.String"},
new Object[]{"a", "b"}
);
方式 B:数组传参(推荐)
genericService.$invoke(
"MultiArgs",
new String[]{"[Ljava.lang.String;"},
new Object[]{new String[]{"a", "b"}}
);
非泛化调用也正常工作,Java 端按普通方法调用即可。
边界条件处理
...interface{}混合类型Checklist
develop