You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by xu...@apache.org on 2026/04/22 06:15:44 UTC

(dubbo-website) branch master updated: docs: update generic invocation docs with Triple protocol support (#3205)

This is an automated email from the ASF dual-hosted git repository.

Alanxtl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-website.git


The following commit(s) were added to refs/heads/master by this push:
     new 1f54f570258 docs: update generic invocation docs with Triple protocol support (#3205)
1f54f570258 is described below

commit 1f54f570258972f76bc353d293e1f807e0d7aba8
Author: Hbzhtd <10...@users.noreply.github.com>
AuthorDate: Wed Apr 22 14:15:39 2026 +0800

    docs: update generic invocation docs with Triple protocol support (#3205)
    
    Align documentation with current dubbo-go main branch implementation:
    
    - Fix serialization overview: describe default Hessian2 behavior instead
      of claiming "only supports Hessian"
    - Update generalizer types from "only Map" to Map/Gson/Protobuf-JSON/Bean
    - Add m struct tag and generic.include.class configuration docs
    - Update Triple section: unified dial flow supports both registry and
      direct connection
    - Fix filter auto-deserialization: OnResponse now supports automatic
      deserialization when reply pointer is set
    - Mark legacy ReferenceConfig approach, recommend client.NewGenericService
    - Remove stale "parameterless call crash" warning (fixed in current code)
    - Add InvokeWithType example using new client.NewGenericService API
    - Add "Generic Mode Selection" section with comparison table
    - Both Chinese and English docs updated
    
    Fixes: apache/dubbo-go#3297
    
    Signed-off-by: GaoJinCheng <ga...@gmail.com>
---
 .../overview/mannual/golang-sdk/refer/generic.md   | 95 +++++++++++++++++++---
 .../overview/mannual/golang-sdk/refer/generic.md   | 95 +++++++++++++++++++---
 2 files changed, 168 insertions(+), 22 deletions(-)

diff --git a/content/en/overview/mannual/golang-sdk/refer/generic.md b/content/en/overview/mannual/golang-sdk/refer/generic.md
index 7350b2440ef..982ec1d8f74 100644
--- a/content/en/overview/mannual/golang-sdk/refer/generic.md
+++ b/content/en/overview/mannual/golang-sdk/refer/generic.md
@@ -9,11 +9,8 @@ title: Generic Invocation
 type: docs
 weight: 2
 ---
-{{% alert title="Deprecation Warning" color="warning" %}}
-dubbo-go generic invocation is only applicable to the dubbo2 protocol, not the triple protocol
-{{% /alert %}}
 
-Generic invocation is a special way of calling in Dubbo-Go that allows intermediary nodes to pass call information without interface information, commonly used in testing and gateway scenarios. Generic invocation supports both Dubbo and Triple protocols, but currently, the serialization scheme only supports Hessian.
+Generic invocation is a special way of calling in Dubbo-Go that allows intermediary nodes to pass call information without interface information, commonly used in testing and gateway scenarios. Generic invocation supports both Dubbo and Triple protocols. When creating a generic service via `client.NewGenericService`, Hessian2 is used as the default transport serialization.
 
 ## Background
 
@@ -31,7 +28,7 @@ Generic invocation essentially transforms a complex structure into a generic str
 
 ![img](/imgs/docs3-v2/golang-sdk/concept/rpc/generic/1632207075184-25939db4-f384-452e-a0b8-e1deff7971de.png)
 
-Currently, Dubbo-go v3 only supports Map generic invocation (default). Taking the User interface as an example, its definition is as follows:
+Dubbo-go v3 supports multiple generic invocation modes, including Map (default), Gson, Protobuf-JSON, and Bean. Among these, Map is the most commonly used. The following uses it as an example. Taking the User interface as an example, its definition is as follows:
 
 ```go
 // definition
@@ -71,12 +68,53 @@ usermap := map[interface{}]interface{} {
 Note that:
 
 - The Map generic invocation will automatically convert the first letter to lowercase, so ID will become iD. If you need to align with Dubbo-Java, consider changing ID to Id;
-- A class field will be automatically inserted into the Map to identify the original interface class.
+- To precisely control the key names in the Map, you can use the `m` struct tag. For example, `` Name string `m:"userName"` `` will set the key to `userName` instead of the default `name`;
+- When the struct implements the `hessian.POJO` interface, a `class` field will be automatically inserted into the generalized result to identify the original interface class. This behavior can be disabled by setting `generic.include.class=false`, which is suitable for generic invocation between pure Go services.
 
 ## Usage
 
 Generic invocation is transparent to the provider side, meaning the provider does not need any explicit configuration to handle generic requests correctly.
 
+### Generic Invocation over Triple Protocol
+
+The Triple protocol (dubbo3) supports generic invocation. `NewGenericService` uses a unified dial flow internally, supporting both service discovery via a registry and direct connection via `client.WithURL`. For a complete example, see [dubbo-go-samples/generic](https://github.com/apache/dubbo-go-samples/tree/main/generic). The following uses direct connection as an example.
+
+First, create a dubbo instance and a client, then create a generic service via `cli.NewGenericService`, as shown below.
+
+```go
+ins, err := dubbo.NewInstance(dubbo.WithName("generic-client"))
+
+cli, err := ins.NewClient(
+	client.WithClientProtocolTriple(),
+	client.WithClientSerialization(constant.Hessian2Serialization),
+)
+
+genericService, err := cli.NewGenericService(
+	"org.apache.dubbo.samples.UserProvider",
+	client.WithURL("tri://127.0.0.1:50052"),
+	client.WithVersion("1.0.0"),
+	client.WithGroup("triple"),
+)
+```
+
+The `NewGenericService` method accepts the following parameters:
+
+- Service interface name;
+- `client.WithURL`: direct connection address, using the `tri://` protocol prefix;
+- `client.WithVersion`: service version;
+- `client.WithGroup`: service group.
+
+Then you can make a generic invocation on the service:
+
+```go
+resp, err := genericService.Invoke(
+	context.Background(),
+	"GetUser1",
+	[]string{"java.lang.String"},
+	[]hessian.Object{"A003"},
+)
+```
+
 ### Based on Dubbo URL Generic Invocation
 
 The generic invocation based on Filter is transparent to the consumer, and a typical application scenario is a gateway. This method requires that the Dubbo URL contains a generic invocation identifier, as follows.
@@ -91,11 +129,13 @@ The semantics expressed by this Dubbo URL are:
 - The org.apache.dubbo.sample.UserProvider interface is located at 127.0.0.1:20000;
 - Using generic invocation (generic=true).
 
-The consumer's Filter will automatically convert normal calls to generic calls based on the configuration carried by the Dubbo URL, but note that in this method, response results will return in generic format and will not automatically convert to the corresponding object. For example, in map generic invocation, if a User class needs to be returned, the consumer will receive a map corresponding to the User class.
+The consumer's Filter will automatically convert normal calls to generic calls based on the configuration carried by the Dubbo URL. When `inv.Reply()` is set to a target struct pointer, the consumer-side Filter will automatically deserialize the map result into the corresponding object during the `OnResponse` phase; if not set, the response will still be returned in generic format (e.g., map).
 
-### Manual Generic Invocation
+### Manual Generic Invocation (Legacy)
 
-Manual generic invocation requests are not processed through a filter; thus, the consumer must explicitly initiate a generic invocation, a typical application scenario for testing. In [dubbo-go-samples](https://github.com/apache/dubbo-go-samples/tree/f7febed9d686cb940ea55d34b5baa567d7574a44/generic), manual invocation is used for ease of testing.
+> It is recommended to use `client.NewGenericService` as described above. The following is the legacy approach based on `config.ReferenceConfig`, provided for reference only.
+
+Manual generic invocation constructs a reference via `config.ReferenceConfig` and explicitly initiates a generic invocation, a typical application scenario for testing.
 
 Generic invocation does not require creating a configuration file (dubbogo.yaml), but requires manual configuration of the registry, reference, and other information in the code. The initialization method is encapsulated in the newRefConf method, as follows.
 
@@ -157,12 +197,12 @@ The Invoke method of GenericService takes four parameters:
 - parameter types: GetUser method accepts a string type parameter. If the target method accepts multiple parameters, you can write it as `[]string{"type1", "type2", ...}`. If the method is parameterless, you need to fill in an empty array `[]string{}`;
 - actual parameters: written the same way as parameter types. If it is a parameterless function, you still need to fill in an empty array `[]hessian.Object{}` as a placeholder.
 
-Note: In the current version, parameterless calls may cause crashing issues.
-
 ### Automatic Deserialization with InvokeWithType
 
 In the `Invoke` method, the return value `resp` is a `map` type (for `MapGeneralizer`), requiring users to manually perform type conversion. To simplify this process, dubbo-go provides the `InvokeWithType` method, which can automatically deserialize the result into a user-specified struct.
 
+The following example uses the `client.NewGenericService` approach:
+
 ```go
 // Define the result struct
 type User struct {
@@ -173,6 +213,24 @@ type User struct {
 
 var user User
 // Deserialize the result directly into the user struct
+err := genericService.InvokeWithType(
+    context.Background(),
+    "GetUser1",
+    []string{"java.lang.String"},
+    []hessian.Object{"A003"},
+    &user,
+)
+
+if err != nil {
+    // Handle error
+}
+fmt.Println(user.Name)
+```
+
+When using the legacy `config.ReferenceConfig` approach, the calling method is as follows:
+
+```go
+var user User
 err := refConf.
     GetRPCService().(*generic.GenericService).
     InvokeWithType(
@@ -191,6 +249,21 @@ fmt.Println(user.Name)
 
 Note: `InvokeWithType` currently only supports the default Map generic invocation.
 
+## Generic Mode Selection
+
+Dubbo-go supports the following four generic invocation modes, distinguished by the `generic` parameter value:
+
+| Mode | Parameter Value | Generalized Format | Use Case |
+|------|----------------|-------------------|----------|
+| Map (default) | `true` | `map[string]any` | General purpose, Go and Java interoperability |
+| Gson | `gson` | JSON string | Scenarios requiring JSON format interaction |
+| Protobuf-JSON | `protobuf-json` | JSON string | Generic invocation of Protobuf messages |
+| Bean | `bean` | `JavaBeanDescriptor` | Alignment with Java Bean serialization |
+
+When using `client.NewGenericService`, the Map mode is used by default. To use other modes, set the `Generic` field in `ReferenceConfig` to the corresponding parameter value.
+
+In most scenarios, the default Map generic mode is recommended.
+
 ## Cross-language RPC contract guidance
 
 In generic invocation or cross-language scenarios, Go variadic method signatures such as `args ...string` can introduce contract ambiguity.
diff --git a/content/zh-cn/overview/mannual/golang-sdk/refer/generic.md b/content/zh-cn/overview/mannual/golang-sdk/refer/generic.md
index 8e2b37ecf12..82babaf04a6 100644
--- a/content/zh-cn/overview/mannual/golang-sdk/refer/generic.md
+++ b/content/zh-cn/overview/mannual/golang-sdk/refer/generic.md
@@ -9,11 +9,8 @@ title: 泛化调用
 type: docs
 weight: 2
 ---
-{{% alert title="废弃警告" color="warning" %}}
-dubbo-go 泛化调用仅适用于 dubbo2 协议,不适用 triple 协议
-{{% /alert %}}
 
-泛化调用是一种 Dubbo-Go 的特殊调用方式,它允许中间节点在没有接口信息的情况下传递调用信息,常被用于测试、网关的场景下。泛化调用支持 Dubbo 和 Triple 协议,但是目前序列化方案只支持 Hessian。
+泛化调用是一种 Dubbo-Go 的特殊调用方式,它允许中间节点在没有接口信息的情况下传递调用信息,常被用于测试、网关的场景下。泛化调用支持 Dubbo 和 Triple 协议。通过 `client.NewGenericService` 创建泛化服务时,默认使用 Hessian2 作为传输序列化方案。
 
 ## 背景
 
@@ -31,7 +28,7 @@ RPC 需要借助网络介质传输,因此数据不能以 go struct 形式传
 
 ![img](/imgs/docs3-v2/golang-sdk/concept/rpc/generic/1632207075184-25939db4-f384-452e-a0b8-e1deff7971de.png)
 
-目前,Dubbo-go v3 只支持 Map 泛化方式(default)。我们以 User 接口为例,其定义如下所示。
+Dubbo-go v3 支持多种泛化方式,包括 Map(默认)、Gson、Protobuf-JSON 和 Bean。其中 Map 泛化方式最为常用,下面以此为例进行说明。以 User 接口为例,其定义如下所示。
 
 ```go
 // definition
@@ -71,12 +68,53 @@ usermap := map[interface{}]interface{} {
 需要注意的是:
 
 - Map 泛化方式会自动将首字母小写,即 ID 会被转换为 iD,如果需要对齐 Dubbo-Java 请考虑将 ID 改为 Id;
-- 在 Map 中会自动插入 class 字段,用于标识原有接口类。
+- 如果需要精确控制 Map 中的 key 名称,可以通过 `m` struct tag 显式指定。例如 `` Name string `m:"userName"` `` 会使 key 变为 `userName` 而非默认的 `name`;
+- 当结构体实现了 `hessian.POJO` 接口时,泛化结果中会自动插入 `class` 字段,用于标识原有接口类。可通过配置 `generic.include.class=false` 关闭此行为,适用于纯 Go 服务间的泛化调用场景。
 
 ## 使用
 
 泛化调用对 provider 端是透明的,即 provider 端不需要任何显式配置就可以正确处理泛化请求。
 
+### 基于 Triple 协议泛化调用
+
+Triple 协议(dubbo3)已支持泛化调用。`NewGenericService` 内部走统一的 dial 流程,既支持通过注册中心发现服务,也支持通过 `client.WithURL` 进行直连调用。完整示例请参见 [dubbo-go-samples/generic](https://github.com/apache/dubbo-go-samples/tree/main/generic)。以下以直连调用为例。
+
+首先创建 dubbo 实例和客户端,然后通过 `cli.NewGenericService` 创建泛化服务,如下所示。
+
+```go
+ins, err := dubbo.NewInstance(dubbo.WithName("generic-client"))
+
+cli, err := ins.NewClient(
+	client.WithClientProtocolTriple(),
+	client.WithClientSerialization(constant.Hessian2Serialization),
+)
+
+genericService, err := cli.NewGenericService(
+	"org.apache.dubbo.samples.UserProvider",
+	client.WithURL("tri://127.0.0.1:50052"),
+	client.WithVersion("1.0.0"),
+	client.WithGroup("triple"),
+)
+```
+
+`NewGenericService` 方法接收的参数分别是:
+
+- 服务接口名;
+- `client.WithURL`: 直连地址,使用 `tri://` 协议前缀;
+- `client.WithVersion`: 服务版本;
+- `client.WithGroup`: 服务分组。
+
+接着可以对服务发起泛化调用:
+
+```go
+resp, err := genericService.Invoke(
+	context.Background(),
+	"GetUser1",
+	[]string{"java.lang.String"},
+	[]hessian.Object{"A003"},
+)
+```
+
 ### 基于 Dubbo URL 泛化调用
 
 基于 Filter 泛化调用对 consumer 是透明的,典型应用场景是网关。这种方式需要要求 Dubbo URL 中包含泛化调用标识,如下所示。
@@ -91,11 +129,13 @@ dubbo://127.0.0.1:20000/org.apache.dubbo.sample.UserProvider?generic=true&...
 - org.apache.dubbo.sample.UserProvider 接口位于 127.0.0.1:20000;
 - 使用泛化调用(generic=true)。
 
-Consumer 端的 Filter 会自动根据 Dubbo URL 携带的配置自动将普通调用转化为泛化调用,但是需要注意的是,在这种方式下响应结果是以泛化格式返回,不会自动转化为相应的对象。举个例子,在 map 泛化方式下,如果需要返回 User 类,那么 consumer 获得的相应是一个 User 类对应的 map。
+Consumer 端的 Filter 会自动根据 Dubbo URL 携带的配置将普通调用转化为泛化调用。当 `inv.Reply()` 设置了目标结构体指针时,consumer 侧 Filter 会在 `OnResponse` 阶段自动将 map 结果反序列化为相应的对象;若未设置,则响应结果仍以泛化格式(如 map)返回。
 
-### 手动泛化调用
+### 手动泛化调用(传统方式)
 
-手动泛化调用发起的请求不经过 filter,所以需要 consumer 端显式地发起泛化调用,典型应用场景是测试。在 [dubbo-go-samples](https://github.com/apache/dubbo-go-samples/tree/f7febed9d686cb940ea55d34b5baa567d7574a44/generic) 中,为了便于测试都是采用手动调用的方式。
+> 推荐使用上文中 `client.NewGenericService` 的方式进行泛化调用,以下为基于 `config.ReferenceConfig` 的传统方式,仅作参考。
+
+手动泛化调用通过 `config.ReferenceConfig` 构建引用并显式发起泛化调用,典型应用场景是测试。
 
 泛化调用不需要创建配置文件(dubbogo.yaml),但是需要在代码中手动配置注册中心、reference 等信息,初始化方法被封装到 newRefConf 方法中,如下所示。
 
@@ -157,12 +197,12 @@ GenericService 的 Invoke 方法接收四个参数,分别是:
 - 参数类型: GetUser 方法接收一个 string 类型的参数,如果目标方法接收多个参数,可以写为 `[]string{"type1", "type2", ...}`,如果目前方法是无参的,则需要填入一个空数组 `[]string{}`;
 - 实参: 写法同参数类型,如果是无参函数,依然要填入一个空数组 `[]hessian.Object{}` 占位。
 
-注意:在目前版本中,无参调用会出现崩溃问题。
-
 ### 泛化调用获取结果自动反序列化
 
 在 `Invoke` 方法中,返回值 `resp` 是一个 `map` 类型(对于 `MapGeneralizer`),用户需要手动进行类型转换。为了简化这一过程,dubbo-go 提供了 `InvokeWithType` 方法,可以将结果自动反序列化为用户指定的结构体。
 
+以下示例基于 `client.NewGenericService` 方式:
+
 ```go
 // 定义结果结构体
 type User struct {
@@ -173,6 +213,24 @@ type User struct {
 
 var user User
 // 直接将结果反序列化到 user 结构体中
+err := genericService.InvokeWithType(
+    context.Background(),
+    "GetUser1",
+    []string{"java.lang.String"},
+    []hessian.Object{"A003"},
+    &user,
+)
+
+if err != nil {
+    // 处理错误
+}
+fmt.Println(user.Name)
+```
+
+如果使用传统的 `config.ReferenceConfig` 方式,调用方式如下:
+
+```go
+var user User
 err := refConf.
     GetRPCService().(*generic.GenericService).
     InvokeWithType(
@@ -191,6 +249,21 @@ fmt.Println(user.Name)
 
 注意:`InvokeWithType` 目前仅支持默认的 Map 泛化方式。
 
+## 泛化方式选择
+
+Dubbo-go 支持以下四种泛化方式,通过 `generic` 参数值区分:
+
+| 泛化方式 | 参数值 | 泛化格式 | 适用场景 |
+|---------|-------|---------|---------|
+| Map(默认) | `true` | `map[string]any` | 通用场景,Go 与 Java 互通 |
+| Gson | `gson` | JSON 字符串 | 需要 JSON 格式交互的场景 |
+| Protobuf-JSON | `protobuf-json` | JSON 字符串 | Protobuf 消息的泛化调用 |
+| Bean | `bean` | `JavaBeanDescriptor` | 与 Java Bean 序列化对齐 |
+
+使用 `client.NewGenericService` 时默认采用 Map 泛化方式。如需使用其他方式,可在 `ReferenceConfig` 中将 `Generic` 字段设置为对应的参数值。
+
+在大多数场景下,推荐使用默认的 Map 泛化方式。
+
 ## 跨语言 RPC 接口定义建议
 
 在泛化调用或跨语言调用场景下,Go 的 variadic 方法签名(例如 `args ...string`)容易引入额外的接口定义歧义。