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

xuetaoli pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-go-samples.git


The following commit(s) were added to refs/heads/main by this push:
     new fc02ccc8 feat(router): add router examples (#1032)
fc02ccc8 is described below

commit fc02ccc8f5b18c885a6d34679cb1587141a1f7df
Author: yangpixi <[email protected]>
AuthorDate: Wed Feb 25 13:00:12 2026 +0800

    feat(router): add router examples (#1032)
    
    * feat(router): add tag router samples
    
    * refactor: change directory name
    
    * style: run imports-formatter to change import order
    
    * docs: add tag samples description in README
    
    * chore: add license header
    
    * docs: refine docs and add Chinese version docs
    
    * style: change wrong application name
    
    * feat(router): add condition router examples.
    
    * chore: add license header
    
    * style: add a blank space
    
    * feat: complete update intergrate test logic (#1034)
    
    * complete update logic
    
    * import format
    
    * add docker compose
    
    * docker-health-check
    
    * warp
    
    * fix all samples
    
    * import format
    
    * delete use less files
    
    * Update integrate_test.sh
    
    Co-authored-by: Copilot <[email protected]>
    
    ---------
    
    Co-authored-by: Copilot <[email protected]>
    
    * chore: add support for ci test
    
    * fix: register tag router into ci test
    
    * feat(router): add script router examples, refine docs
    
    * chore: change directory name, add gracefully exits code.
    
    * fix: resolve all problems.
    
    * fix: remove useless function.
    
    ---------
    
    Co-authored-by: Xuetao Li <[email protected]>
    Co-authored-by: Copilot <[email protected]>
---
 README.md                                          |   4 +
 README_CN.md                                       |   4 +
 router/README.md                                   |   7 +
 router/README_CN.md                                |   7 +
 router/condition/README.md                         |  68 ++++++
 router/condition/README_CN.md                      |  67 ++++++
 router/condition/go-client/cmd/client.go           |  96 +++++++++
 .../condition/go-node2-server/cmd/server_node2.go  |  90 ++++++++
 router/condition/go-server/cmd/server.go           |  90 ++++++++
 router/script/README.md                            |  69 +++++++
 router/script/README_CN.md                         |  66 ++++++
 router/script/go-client/cmd/client.go              |  96 +++++++++
 router/script/go-node2-server/cmd/server_node2.go  |  90 ++++++++
 router/script/go-server/cmd/server.go              |  90 ++++++++
 router/tag/README.md                               |  33 +++
 router/tag/README_CN.md                            |  33 +++
 router/tag/go-client/cmd/client.go                 | 102 +++++++++
 router/tag/go-server/cmd/server.go                 |  91 ++++++++
 router/tag/go-tag-server/cmd/server_tag.go         |  91 ++++++++
 router/tag/proto/greet.pb.go                       | 230 +++++++++++++++++++++
 router/tag/proto/greet.proto                       |  34 +++
 router/tag/proto/greet.triple.go                   | 122 +++++++++++
 start_integrate_test.sh                            |   3 +
 23 files changed, 1583 insertions(+)

diff --git a/README.md b/README.md
index 13621857..88903866 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,10 @@ Please refer to [HOWTO.md](HOWTO.md) for detailed 
instructions on running the sa
   * `otlp_http_exporter`: Uses `otlpHttpExporter` to export tracing data, 
covering `dubbo`/`triple`/`jsonrpc` protocols.
 * `registry`: Examples of using different service registries (e.g., Nacos, 
Zookeeper).
 * `retry`: Demonstrates retry mechanisms in Dubbo-go RPC calls.
+* `router`: Various Dubbo-go router examples.
+  * `router/tag`: Dubbo-go tag router examples.
+  * `router/condition`: Dubbo-go condition router examples.
+  * `router/script`: Dubbo-go script router examples.
 * `rpc`: Various RPC protocol examples with Dubbo-go.
   * `rpc/dubbo`: Dubbo protocol example, including Java–Go interop.
   * `rpc/grpc`: gRPC protocol example.
diff --git a/README_CN.md b/README_CN.md
index 4971c954..1c0940a1 100644
--- a/README_CN.md
+++ b/README_CN.md
@@ -44,6 +44,10 @@
   * `otlp_http_exporter`:使用 `otlpHttpExporter` 导出追踪数据,覆盖 `dubbo` / `triple` / 
`jsonrpc` 协议。
 * `registry`:使用不同服务注册中心(如 Nacos、Zookeeper)的示例。
 * `retry`:Dubbo-go RPC 调用重试机制示例。
+* `router`: Dubbo-go 各种 Router 调用示例。
+  * `router/tag`: Dubbo-go 的 tag router 使用示例。
+  * `router/condition`: Dubbo-go 的 condition router 使用示例。
+  * `router/script`: Dubbo-go 的 script router 使用示例。
 * `rpc`:Dubbo-go 支持的多种 RPC 协议示例。
   * `rpc/dubbo`:Dubbo 协议示例,包含 Java–Go 互操作。
   * `rpc/grpc`:基于 gRPC 协议的示例。
diff --git a/router/README.md b/router/README.md
new file mode 100644
index 00000000..07d9f400
--- /dev/null
+++ b/router/README.md
@@ -0,0 +1,7 @@
+# Dubbo-go Router Sample
+
+English | [中文](README_CN.md)
+
+## Description
+
+This directory includes multiple types of dubbo-go router function.
\ No newline at end of file
diff --git a/router/README_CN.md b/router/README_CN.md
new file mode 100644
index 00000000..abc077db
--- /dev/null
+++ b/router/README_CN.md
@@ -0,0 +1,7 @@
+# Dubbo-go Router 示例
+
+[English](README.md) | 中文
+
+## 描述
+
+这个文件夹包含了 dubbo-go router 功能的多个示例。
\ No newline at end of file
diff --git a/router/condition/README.md b/router/condition/README.md
new file mode 100644
index 00000000..0d43c023
--- /dev/null
+++ b/router/condition/README.md
@@ -0,0 +1,68 @@
+# Condition router
+
+This example shows how to use dubbo-go's condition router.
+
+English | [中文](README_CN.md)
+
+## Prerequisites
+
+- Docker and docker compose to run Nacos registry.
+- Go Version 1.23+.
+- Nacos Version 2.x+.
+
+## How to run
+
+### Run Nacos registry
+
+Follow this instruction
+to [install and run 
Nacos](https://dubbo-next.staged.apache.org/zh-cn/overview/reference/integrations/nacos/).
+
+### Run server (Provider)
+
+In this example, you will run two servers on ports 20000 and 20001 
respectively.
+
+```shell
+$ go run ./go-server/cmd/server.go              # port 20000
+$ go run ./go-node2-server/cmd/server_node2.go  # port 20001
+```
+
+### Run client (Consumer)
+
+In this example, the client will keep calling Greet method in an infinity 
loop. You need to:
+
+- Start the client and observe the load balancing behavior during calls.
+
+- Set up the condition router configuration in the Nacos registry, then 
observe the client's calls again.
+
+```shell
+$ go run ./go-client/cmd/client.go
+```
+
+### Configuration of Nacos
+
+Create a new configuration with the `Data ID` 
**condition-server.condition-router** and set the format to `yaml`.
+
+Set the Group to `DEFAULT_GROUP`.
+
+> Note: The naming convention in Nacos is {application.name}.{router_type}.
+
+```yaml
+configVersion: V3.3.2
+scope: "application"
+key: "condition-server"
+priority: 1
+force: true
+enabled: true
+conditions:
+  - from:
+      match: "application = condition-client"
+    to:
+      - match: "port = 20001"
+```
+
+## Expected result
+
+- When the client starts without the condition router configuration in Nacos,
+  it will alternate calls between the two server endpoints.
+- When the client starts with the condition router configured in Nacos,
+  it will route traffic to only one server endpoint.
diff --git a/router/condition/README_CN.md b/router/condition/README_CN.md
new file mode 100644
index 00000000..294e8476
--- /dev/null
+++ b/router/condition/README_CN.md
@@ -0,0 +1,67 @@
+# Condition router
+
+这个例子展示了如何使用dubbo-go的condition router功能。
+
+[English](README.md) | 中文
+
+## 前置准备
+
+- Docker以及Docker Compose环境来运行Nacos注册中心。
+- Go 1.23+版本。
+- Nacos 2.x+版本。
+
+## 如何运行
+
+### 启动Nacos注册中心
+
+参考这个教程来[启动Nacos](https://dubbo-next.staged.apache.org/zh-cn/overview/reference/integrations/nacos/)。
+
+### 运行服务端(Provider)
+
+在这个示例中,你将运行两个服务端,分别在20000以及20001端口上提供服务。
+
+```shell
+$ go run ./go-server/cmd/server.go              # 20000端口
+$ go run ./go-node2-server/cmd/server_node2.go  # 20001端口
+```
+
+### 运行客户端(Consumer)
+
+在这个示例中,客户端将在一个死循环中一直调用Greet方法,你需要:
+
+- 启动客户端,观察其调用时的负载均衡(Load Balance)。
+- 在Nacos注册中心上设置`condition router`的配置,再次观察客户端的调用情况。
+
+```shell
+$ go run ./go-client/cmd/client.go
+```
+
+### Nacos配置
+
+新建一个`Data ID`为`condition-server.condition-router`,格式为`yaml`的配置。
+
+Group设置为`DEFAULT_GROUP`。
+
+> 注意:Nacos中命名规则为{application.name}.{router_type}
+
+```yaml
+configVersion: V3.3.2
+scope: "application"
+key: "condition-server"
+priority: 1
+force: true
+enabled: true
+conditions:
+  - from:
+      match: "application = condition-client"
+    to:
+      - match: "port = 20001"
+```
+
+## 预期结果
+
+- 启动客户端但是未在nacos配置中心设置condition router的配置的时候,客户端将在两个服务端之间来回调用。
+- 启动客户端并在nacos配置中心设置了condition router后,客户端将只调用其中一个服务端。
+
+
+
diff --git a/router/condition/go-client/cmd/client.go 
b/router/condition/go-client/cmd/client.go
new file mode 100644
index 00000000..a926cfae
--- /dev/null
+++ b/router/condition/go-client/cmd/client.go
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "os/signal"
+       "syscall"
+       "time"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       "dubbo.apache.org/dubbo-go/v3/config_center"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+)
+
+func main() {
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("condition-client"),
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithConfigCenter( // configure config center to enable 
condition router
+                       config_center.WithNacos(),
+                       config_center.WithAddress(RegistryAddress),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new instance failed: %v", err)
+               panic(err)
+       }
+
+       cli, err := ins.NewClient()
+
+       if err != nil {
+               logger.Errorf("new client failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := greet.NewGreetService(cli)
+
+       if err != nil {
+               logger.Errorf("new service failed: %v", err)
+               panic(err)
+       }
+
+       ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, 
syscall.SIGTERM)
+       defer stop()
+
+       ticker := time.NewTicker(5 * time.Second)
+       defer ticker.Stop()
+
+       for {
+               select {
+               case <-ctx.Done():
+                       logger.Info("gracefully exiting...")
+                       return
+               case <-ticker.C:
+                       rep, err := srv.Greet(context.Background(), 
&greet.GreetRequest{Name: "hello world"})
+                       if err != nil {
+                               logger.Errorf("call greet method failed: %v", 
err)
+                       } else {
+                               logger.Infof("receive: %s", rep.GetGreeting())
+                       }
+               }
+       }
+}
diff --git a/router/condition/go-node2-server/cmd/server_node2.go 
b/router/condition/go-node2-server/cmd/server_node2.go
new file mode 100644
index 00000000..26d60907
--- /dev/null
+++ b/router/condition/go-node2-server/cmd/server_node2.go
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "strconv"
+       "strings"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+       TriPort         = 20000
+)
+
+type GreetServer struct {
+       srvPort int
+}
+
+func (srv *GreetServer) Greet(_ context.Context, req *greet.GreetRequest) (rep 
*greet.GreetResponse, err error) {
+       rep = &greet.GreetResponse{Greeting: req.Name + " from: " + 
strconv.Itoa(srv.srvPort)}
+       return rep, nil
+}
+
+func main() {
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("condition-server"),
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithProtocol(
+                       protocol.WithTriple(),
+                       protocol.WithPort(TriPort),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new instance failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := ins.NewServer()
+
+       if err != nil {
+               logger.Errorf("new server failed: %v", err)
+               panic(err)
+       }
+
+       if err := greet.RegisterGreetServiceHandler(srv, &GreetServer{srvPort: 
TriPort}); err != nil {
+               logger.Errorf("register service failed: %v", err)
+               panic(err)
+       }
+
+       if err := srv.Serve(); err != nil {
+               logger.Errorf("server serve failed: %v", err)
+               if strings.Contains(err.Error(), "client not connected") {
+                       logger.Errorf("hint: Nacos client not connected (gRPC). 
Check %s is reachable and gRPC port %d is open (Nacos 2.x default).", 
RegistryAddress, 9848)
+               }
+               panic(err)
+       }
+}
diff --git a/router/condition/go-server/cmd/server.go 
b/router/condition/go-server/cmd/server.go
new file mode 100644
index 00000000..2bf78c01
--- /dev/null
+++ b/router/condition/go-server/cmd/server.go
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "strconv"
+       "strings"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+       TriPort         = 20001
+)
+
+type GreetServer struct {
+       srvPort int
+}
+
+func (srv *GreetServer) Greet(_ context.Context, req *greet.GreetRequest) (rep 
*greet.GreetResponse, err error) {
+       rep = &greet.GreetResponse{Greeting: req.Name + " from: " + 
strconv.Itoa(srv.srvPort)}
+       return rep, nil
+}
+
+func main() {
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("condition-server"),
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithProtocol(
+                       protocol.WithTriple(),
+                       protocol.WithPort(TriPort),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new instance failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := ins.NewServer()
+
+       if err != nil {
+               logger.Errorf("new server failed: %v", err)
+               panic(err)
+       }
+
+       if err := greet.RegisterGreetServiceHandler(srv, &GreetServer{srvPort: 
TriPort}); err != nil {
+               logger.Errorf("register service failed: %v", err)
+               panic(err)
+       }
+
+       if err := srv.Serve(); err != nil {
+               logger.Errorf("server serve failed: %v", err)
+               if strings.Contains(err.Error(), "client not connected") {
+                       logger.Errorf("hint: Nacos client not connected (gRPC). 
Check %s is reachable and gRPC port %d is open (Nacos 2.x default).", 
RegistryAddress, 9848)
+               }
+               panic(err)
+       }
+}
diff --git a/router/script/README.md b/router/script/README.md
new file mode 100644
index 00000000..4fc14f73
--- /dev/null
+++ b/router/script/README.md
@@ -0,0 +1,69 @@
+# Script Router
+
+This example demonstrates how to use the script router feature in dubbo-go.
+
+English | [中文](README_CN.md)
+
+## Prerequisites
+
+- Docker and Docker Compose environment to run the Nacos registry.
+- Go version 1.23+.
+- Nacos version 2.x+.
+
+## How to Run
+
+### Start Nacos Registry
+
+Follow this instruction to [install and start Nacos 
server](https://dubbo-next.staged.apache.org/zh-cn/overview/reference/integrations/nacos/).
+
+### Run Server (Provider)
+
+In this example, you will run two servers providing services on ports 20000 
and 20001 respectively.
+
+```Shell
+$ go run ./go-server/cmd/server.go              # port 20000
+$ go run ./go-node2-server/cmd/server_node2.go  # port 20001
+```
+
+### Run Client (Consumer)
+
+In this example, the client will continuously call the Greet method in an 
infinite loop. You need to:
+
+- Start the client and observe the load balancing behavior during calls.
+
+- Set up the script router configuration in the Nacos registry, then observe 
the client's calls again.
+
+```Shell
+$ go run ./go-client/cmd/client.go
+```
+
+### Nacos Configuration
+
+Create a new configuration with the `Data ID` **script-server.script-router** 
and set the format to `yaml`.
+
+Set the Group to `DEFAULT_GROUP`.
+
+> Note: The naming convention in Nacos is {application.name}.{router_type}.
+
+```yaml
+scope: "application"
+key: "script-server"
+enabled: true
+type: "javascript"
+script: |
+  (function(invokers, invocation, context) {
+    if (!invokers || invokers.length === 0) return [];
+    return invokers.filter(function(invoker) {
+      var url = invoker.GetURL();
+      return url && url.Port === "20000";
+    });
+  })(invokers, invocation, context);
+```
+
+## Expected Results
+
+- When the client is started without the script router configuration in the 
Nacos config center, the client will alternate
+  calls between the two servers.
+
+- After starting the client and configuring the script router in Nacos, the 
client will only call one specific server (
+  port 20000).
\ No newline at end of file
diff --git a/router/script/README_CN.md b/router/script/README_CN.md
new file mode 100644
index 00000000..7ae157d0
--- /dev/null
+++ b/router/script/README_CN.md
@@ -0,0 +1,66 @@
+# Script router
+
+这个例子展示了如何使用dubbo-go的script router功能。
+
+[English](README.md) | 中文
+
+## 前置准备
+
+- Docker以及Docker Compose环境来运行Nacos注册中心。
+- Go 1.23+版本。
+- Nacos 2.x+版本。
+
+## 如何运行
+
+### 启动Nacos注册中心
+
+参考这个教程来[启动Nacos](https://dubbo-next.staged.apache.org/zh-cn/overview/reference/integrations/nacos/)。
+
+## 运行服务端(Provider)
+
+在这个示例中,你将运行两个服务端,分别在20000以及20001端口上提供服务。
+
+```shell
+$ go run ./go-server/cmd/server.go              # 20000端口
+$ go run ./go-node2-server/cmd/server_node2.go  # 20001端口
+```
+
+### 运行客户端(Consumer)
+
+在这个示例中,客户端将在一个死循环中一直调用Greet方法,你需要:
+
+- 启动客户端,观察其调用时的负载均衡(Load Balance)。
+- 在Nacos注册中心上设置`script router`的配置,再次观察客户端的调用情况。
+
+```shell
+$ go run ./go-client/cmd/client.go
+```
+
+### Nacos配置
+
+新建一个`Data ID`为`script-server.script-router`,格式为`yaml`的配置。
+
+Group设置为`DEFAULT_GROUP`。
+
+> 注意:Nacos中命名规则为{application.name}.{router_type}
+
+```yaml
+scope: "application"
+key: "script-server"
+enabled: true
+type: "javascript"
+script: |
+  (function(invokers, invocation, context) {
+    if (!invokers || invokers.length === 0) return [];
+    return invokers.filter(function(invoker) {
+      var url = invoker.GetURL();
+      return url && url.Port === "20000";
+    });
+  })(invokers, invocation, context);
+```
+
+## 预期结果
+
+- 启动客户端但是未在nacos配置中心设置script router的配置的时候,客户端将在两个服务端之间来回调用。
+- 启动客户端并在nacos配置中心设置了script router后,客户端将只调用其中一个服务端。
+
diff --git a/router/script/go-client/cmd/client.go 
b/router/script/go-client/cmd/client.go
new file mode 100644
index 00000000..2ffb9afd
--- /dev/null
+++ b/router/script/go-client/cmd/client.go
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "os/signal"
+       "syscall"
+       "time"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       "dubbo.apache.org/dubbo-go/v3/config_center"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+)
+
+func main() {
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("script-client"),
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithConfigCenter( // configure config center to enable 
script router
+                       config_center.WithNacos(),
+                       config_center.WithAddress(RegistryAddress),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new instance failed: %v", err)
+               panic(err)
+       }
+
+       cli, err := ins.NewClient()
+
+       if err != nil {
+               logger.Errorf("new client failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := greet.NewGreetService(cli)
+
+       if err != nil {
+               logger.Errorf("new service failed: %v", err)
+               panic(err)
+       }
+
+       ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, 
syscall.SIGTERM)
+       defer stop()
+
+       ticker := time.NewTicker(5 * time.Second)
+       defer ticker.Stop()
+
+       for {
+               select {
+               case <-ctx.Done():
+                       logger.Info("gracefully exiting...")
+                       return
+               case <-ticker.C:
+                       rep, err := srv.Greet(context.Background(), 
&greet.GreetRequest{Name: "hello world"})
+                       if err != nil {
+                               logger.Errorf("call greet method failed: %v", 
err)
+                       } else {
+                               logger.Infof("receive: %s", rep.GetGreeting())
+                       }
+               }
+       }
+}
diff --git a/router/script/go-node2-server/cmd/server_node2.go 
b/router/script/go-node2-server/cmd/server_node2.go
new file mode 100644
index 00000000..f7009d1d
--- /dev/null
+++ b/router/script/go-node2-server/cmd/server_node2.go
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "strconv"
+       "strings"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+       TriPort         = 20000
+)
+
+type GreetServer struct {
+       srvPort int
+}
+
+func (srv *GreetServer) Greet(_ context.Context, req *greet.GreetRequest) (rep 
*greet.GreetResponse, err error) {
+       rep = &greet.GreetResponse{Greeting: req.Name + " from: " + 
strconv.Itoa(srv.srvPort)}
+       return rep, nil
+}
+
+func main() {
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("script-server"),
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithProtocol(
+                       protocol.WithTriple(),
+                       protocol.WithPort(TriPort),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new instance failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := ins.NewServer()
+
+       if err != nil {
+               logger.Errorf("new server failed: %v", err)
+               panic(err)
+       }
+
+       if err := greet.RegisterGreetServiceHandler(srv, &GreetServer{srvPort: 
TriPort}); err != nil {
+               logger.Errorf("register service failed: %v", err)
+               panic(err)
+       }
+
+       if err := srv.Serve(); err != nil {
+               logger.Errorf("server serve failed: %v", err)
+               if strings.Contains(err.Error(), "client not connected") {
+                       logger.Errorf("hint: Nacos client not connected (gRPC). 
Check %s is reachable and gRPC port %d is open (Nacos 2.x default).", 
RegistryAddress, 9848)
+               }
+               panic(err)
+       }
+}
diff --git a/router/script/go-server/cmd/server.go 
b/router/script/go-server/cmd/server.go
new file mode 100644
index 00000000..d8df505b
--- /dev/null
+++ b/router/script/go-server/cmd/server.go
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "strconv"
+       "strings"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/direct/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+       TriPort         = 20001
+)
+
+type GreetServer struct {
+       srvPort int
+}
+
+func (srv *GreetServer) Greet(_ context.Context, req *greet.GreetRequest) (rep 
*greet.GreetResponse, err error) {
+       rep = &greet.GreetResponse{Greeting: req.Name + " from: " + 
strconv.Itoa(srv.srvPort)}
+       return rep, nil
+}
+
+func main() {
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("script-server"),
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithProtocol(
+                       protocol.WithTriple(),
+                       protocol.WithPort(TriPort),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new instance failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := ins.NewServer()
+
+       if err != nil {
+               logger.Errorf("new server failed: %v", err)
+               panic(err)
+       }
+
+       if err := greet.RegisterGreetServiceHandler(srv, &GreetServer{srvPort: 
TriPort}); err != nil {
+               logger.Errorf("register service failed: %v", err)
+               panic(err)
+       }
+
+       if err := srv.Serve(); err != nil {
+               logger.Errorf("server serve failed: %v", err)
+               if strings.Contains(err.Error(), "client not connected") {
+                       logger.Errorf("hint: Nacos client not connected (gRPC). 
Check %s is reachable and gRPC port %d is open (Nacos 2.x default).", 
RegistryAddress, 9848)
+               }
+               panic(err)
+       }
+}
diff --git a/router/tag/README.md b/router/tag/README.md
new file mode 100644
index 00000000..575f25fe
--- /dev/null
+++ b/router/tag/README.md
@@ -0,0 +1,33 @@
+# Tag router
+This example shows how to use dubbo-go tag router ability.
+
+## Prerequisites
+
+- Docker and Docker Compose for running Nacos registry.
+- Go 1.23+ for Dubbo-Go examples.
+
+## How to run
+
+### Start Nacos server
+Follow this instruction to [install and start Nacos 
server](https://dubbo-next.staged.apache.org/zh-cn/overview/reference/integrations/nacos/).
+
+### Run server
+In this example, you need to run two different server with one with tag and 
another without.
+
+```shell
+$ go run ./go-server/cmd/server.go          # non-tagged server
+$ go run ./go-tag-server/cmd/server_tag.go  # tagged server
+```
+
+### Run client
+
+```shell
+$ go run ./go-client/cmd/client.go
+```
+
+## Expected outputs
+
+- ✔ invoke successfully : receive: tag with force, response from: 
server-with-tag
+- ❌ invoke failed: Failed to invoke the method Greet.
+- ✔ invoke successfully : receive: tag with no-force, response from: 
server-without-tag
+- ✔ invoke successfully : receive: non-tag, response from: server-without-tag
diff --git a/router/tag/README_CN.md b/router/tag/README_CN.md
new file mode 100644
index 00000000..878eeb6b
--- /dev/null
+++ b/router/tag/README_CN.md
@@ -0,0 +1,33 @@
+# Tag router
+这个例子展示了如何使用dubbo-go的tag router功能。
+
+## 前置准备
+
+- Docker以及Docker Compose环境来运行Nacos注册中心。
+- Go 1.23+版本。
+
+## 如何运行
+
+### 启动Nacos注册中心
+参考这个教程来[启动Nacos](https://dubbo-next.staged.apache.org/zh-cn/overview/reference/integrations/nacos/)。
+
+### 运行服务端(Provider)
+在这个示例中,你将运行一个具有tag的server以及一个不具有tag的server。
+
+```shell
+$ go run ./go-server/cmd/server.go          # 无标签server
+$ go run ./go-tag-server/cmdserver_tag.go   # 有标签server
+```
+
+### 运行客户端(Consumer)
+
+```shell
+$ go run ./go-client/cmd/client.go
+```
+
+## 预期结果
+
+- ✔ invoke successfully : receive: tag with force, response from: 
server-with-tag
+- ❌ invoke failed: Failed to invoke the method Greet.
+- ✔ invoke successfully : receive: tag with no-force, response from: 
server-without-tag
+- ✔ invoke successfully : receive: non-tag, response from: server-without-tag
diff --git a/router/tag/go-client/cmd/client.go 
b/router/tag/go-client/cmd/client.go
new file mode 100644
index 00000000..ff4a4178
--- /dev/null
+++ b/router/tag/go-client/cmd/client.go
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "strings"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/router/tag/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+)
+
+func main() {
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("tag-client"),
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new instance failed: %v", err)
+               panic(err)
+       }
+
+       cli, err := ins.NewClient()
+
+       if err != nil {
+               logger.Errorf("new client failed: %v", err)
+               panic(err)
+       }
+
+       svc, err := greet.NewGreetService(cli)
+
+       if err != nil {
+               logger.Errorf("new service failed: %v", err)
+               panic(err)
+       }
+
+       callGreet := func(name, tag, force, exp string) {
+               // set tag attachments for invocation
+               atta := map[string]string{
+                       constant.Tagkey:      tag,
+                       constant.ForceUseTag: force,
+               }
+               ctx := context.WithValue(context.Background(), 
constant.AttachmentKey, atta)
+
+               rep, err := svc.Greet(ctx, &greet.GreetRequest{Name: name})
+               // temporarily cancel checking for result, for PR # 3208 
(https://github.com/apache/dubbo-go/pull/3208)
+               // hasn't been merged to main branch yet, thus tag router still 
not works properly.
+
+               //checkRes(exp, resp.GetGreeting(), err)
+               if err != nil {
+                       logger.Errorf("❌ invoke failed: %v", err)
+               } else {
+                       logger.Infof("✔ invoke successfully : %v", rep.Greeting)
+               }
+       }
+
+       callGreet("tag with force", "test-tag", "true", "server-with-tag")      
   // success
+       callGreet("tag with force", "test-tag1", "true", "fail")                
   // fail
+       callGreet("tag with no-force", "test-tag1", "false", 
"server-without-tag") // success
+       callGreet("non-tag", "", "false", "server-without-tag")                 
   // success
+}
+
+func checkRes(exp string, act string, err error) {
+       if (err == nil && exp == "fail") || (err != nil && exp != "fail") {
+               panic("unexpected result!")
+       } else if act != "" && !strings.Contains(act, exp) {
+               panic("unexpected result!")
+       }
+}
diff --git a/router/tag/go-server/cmd/server.go 
b/router/tag/go-server/cmd/server.go
new file mode 100644
index 00000000..08759d3e
--- /dev/null
+++ b/router/tag/go-server/cmd/server.go
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "strings"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/router/tag/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+)
+
+type GreetServer struct {
+       srvName string
+}
+
+func (srv *GreetServer) Greet(_ context.Context, req *greet.GreetRequest) 
(*greet.GreetResponse, error) {
+       rep := &greet.GreetResponse{Greeting: "receive: " + req.Name + ", 
response from: " + srv.srvName}
+       return rep, nil
+}
+
+func main() {
+
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("tag-server"),
+               dubbo.WithTag(""), // set application's tag
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithProtocol(
+                       protocol.WithTriple(),
+                       protocol.WithPort(20000),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new dubbo instance failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := ins.NewServer()
+
+       if err != nil {
+               logger.Errorf("new dubbo server failed: %v", err)
+               panic(err)
+       }
+
+       if err := greet.RegisterGreetServiceHandler(srv, &GreetServer{srvName: 
"server-without-tag"}); err != nil {
+               logger.Errorf("register greet handler failed: %v", err)
+               panic(err)
+       }
+
+       if err := srv.Serve(); err != nil {
+               logger.Errorf("server serve failed: %v", err)
+               if strings.Contains(err.Error(), "client not connected") {
+                       logger.Errorf("hint: Nacos client not connected (gRPC). 
Check %s is reachable and gRPC port %d is open (Nacos 2.x default).", 
RegistryAddress, 9848)
+               }
+               panic(err)
+       }
+
+}
diff --git a/router/tag/go-tag-server/cmd/server_tag.go 
b/router/tag/go-tag-server/cmd/server_tag.go
new file mode 100644
index 00000000..7759b992
--- /dev/null
+++ b/router/tag/go-tag-server/cmd/server_tag.go
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package main
+
+import (
+       "context"
+       "strings"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
+       "dubbo.apache.org/dubbo-go/v3/registry"
+
+       "github.com/dubbogo/gost/log/logger"
+)
+
+import (
+       greet "github.com/apache/dubbo-go-samples/router/tag/proto"
+)
+
+const (
+       RegistryAddress = "127.0.0.1:8848"
+)
+
+type GreetServer struct {
+       srvName string
+}
+
+func (srv *GreetServer) Greet(_ context.Context, req *greet.GreetRequest) 
(*greet.GreetResponse, error) {
+       rep := &greet.GreetResponse{Greeting: "receive: " + req.Name + ", 
response from: " + srv.srvName}
+       return rep, nil
+}
+
+func main() {
+
+       ins, err := dubbo.NewInstance(
+               dubbo.WithName("tag-server"),
+               dubbo.WithTag("test-tag"), // set application's tag
+               dubbo.WithRegistry(
+                       registry.WithNacos(),
+                       registry.WithAddress(RegistryAddress),
+               ),
+               dubbo.WithProtocol(
+                       protocol.WithTriple(),
+                       protocol.WithPort(20001),
+               ),
+       )
+
+       if err != nil {
+               logger.Errorf("new dubbo instance failed: %v", err)
+               panic(err)
+       }
+
+       srv, err := ins.NewServer()
+
+       if err != nil {
+               logger.Errorf("new dubbo server failed: %v", err)
+               panic(err)
+       }
+
+       if err := greet.RegisterGreetServiceHandler(srv, &GreetServer{srvName: 
"server-with-tag"}); err != nil {
+               logger.Errorf("register greet handler failed: %v", err)
+               panic(err)
+       }
+
+       if err := srv.Serve(); err != nil {
+               logger.Errorf("server serve failed: %v", err)
+               if strings.Contains(err.Error(), "client not connected") {
+                       logger.Errorf("hint: Nacos client not connected (gRPC). 
Check %s is reachable and gRPC port %d is open (Nacos 2.x default).", 
RegistryAddress, 9848)
+               }
+               panic(err)
+       }
+
+}
diff --git a/router/tag/proto/greet.pb.go b/router/tag/proto/greet.pb.go
new file mode 100644
index 00000000..8442fbba
--- /dev/null
+++ b/router/tag/proto/greet.pb.go
@@ -0,0 +1,230 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+//     protoc-gen-go v1.31.0
+//     protoc        v6.33.2
+// source: proto/greet.proto
+
+package greet
+
+import (
+       protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+       protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+       reflect "reflect"
+       sync "sync"
+)
+
+const (
+       // Verify that this generated code is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+       // Verify that runtime/protoimpl is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type GreetRequest struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Name string `protobuf:"bytes,1,opt,name=name,proto3" 
json:"name,omitempty"`
+}
+
+func (x *GreetRequest) Reset() {
+       *x = GreetRequest{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_greet_proto_msgTypes[0]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *GreetRequest) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetRequest) ProtoMessage() {}
+
+func (x *GreetRequest) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_greet_proto_msgTypes[0]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetRequest.ProtoReflect.Descriptor instead.
+func (*GreetRequest) Descriptor() ([]byte, []int) {
+       return file_proto_greet_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *GreetRequest) GetName() string {
+       if x != nil {
+               return x.Name
+       }
+       return ""
+}
+
+type GreetResponse struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Greeting string `protobuf:"bytes,1,opt,name=greeting,proto3" 
json:"greeting,omitempty"`
+}
+
+func (x *GreetResponse) Reset() {
+       *x = GreetResponse{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_proto_greet_proto_msgTypes[1]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *GreetResponse) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*GreetResponse) ProtoMessage() {}
+
+func (x *GreetResponse) ProtoReflect() protoreflect.Message {
+       mi := &file_proto_greet_proto_msgTypes[1]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use GreetResponse.ProtoReflect.Descriptor instead.
+func (*GreetResponse) Descriptor() ([]byte, []int) {
+       return file_proto_greet_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *GreetResponse) GetGreeting() string {
+       if x != nil {
+               return x.Greeting
+       }
+       return ""
+}
+
+var File_proto_greet_proto protoreflect.FileDescriptor
+
+var file_proto_greet_proto_rawDesc = []byte{
+       0x0a, 0x11, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x72, 0x65, 0x65, 
0x74, 0x2e, 0x70, 0x72,
+       0x6f, 0x74, 0x6f, 0x12, 0x05, 0x67, 0x72, 0x65, 0x65, 0x74, 0x22, 0x22, 
0x0a, 0x0c, 0x47, 0x72,
+       0x65, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 
0x0a, 0x04, 0x6e, 0x61,
+       0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 
0x6d, 0x65, 0x22, 0x2b,
+       0x0a, 0x0d, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 
0x6e, 0x73, 0x65, 0x12,
+       0x1a, 0x0a, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x18, 
0x01, 0x20, 0x01, 0x28,
+       0x09, 0x52, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x32, 
0x42, 0x0a, 0x0c, 0x47,
+       0x72, 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 
0x32, 0x0a, 0x05, 0x47,
+       0x72, 0x65, 0x65, 0x74, 0x12, 0x13, 0x2e, 0x67, 0x72, 0x65, 0x65, 0x74, 
0x2e, 0x47, 0x72, 0x65,
+       0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 
0x67, 0x72, 0x65, 0x65,
+       0x74, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 
0x6e, 0x73, 0x65, 0x42,
+       0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 
0x6d, 0x2f, 0x61, 0x70,
+       0x61, 0x63, 0x68, 0x65, 0x2f, 0x64, 0x75, 0x62, 0x62, 0x6f, 0x2d, 0x67, 
0x6f, 0x2d, 0x73, 0x61,
+       0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 
0x2f, 0x74, 0x61, 0x67,
+       0x2d, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 
0x6f, 0x3b, 0x67, 0x72,
+       0x65, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+       file_proto_greet_proto_rawDescOnce sync.Once
+       file_proto_greet_proto_rawDescData = file_proto_greet_proto_rawDesc
+)
+
+func file_proto_greet_proto_rawDescGZIP() []byte {
+       file_proto_greet_proto_rawDescOnce.Do(func() {
+               file_proto_greet_proto_rawDescData = 
protoimpl.X.CompressGZIP(file_proto_greet_proto_rawDescData)
+       })
+       return file_proto_greet_proto_rawDescData
+}
+
+var file_proto_greet_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_proto_greet_proto_goTypes = []interface{}{
+       (*GreetRequest)(nil),  // 0: greet.GreetRequest
+       (*GreetResponse)(nil), // 1: greet.GreetResponse
+}
+var file_proto_greet_proto_depIdxs = []int32{
+       0, // 0: greet.GreetService.Greet:input_type -> greet.GreetRequest
+       1, // 1: greet.GreetService.Greet:output_type -> greet.GreetResponse
+       1, // [1:2] is the sub-list for method output_type
+       0, // [0:1] is the sub-list for method input_type
+       0, // [0:0] is the sub-list for extension type_name
+       0, // [0:0] is the sub-list for extension extendee
+       0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_proto_greet_proto_init() }
+func file_proto_greet_proto_init() {
+       if File_proto_greet_proto != nil {
+               return
+       }
+       if !protoimpl.UnsafeEnabled {
+               file_proto_greet_proto_msgTypes[0].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*GreetRequest); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_proto_greet_proto_msgTypes[1].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*GreetResponse); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+       }
+       type x struct{}
+       out := protoimpl.TypeBuilder{
+               File: protoimpl.DescBuilder{
+                       GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+                       RawDescriptor: file_proto_greet_proto_rawDesc,
+                       NumEnums:      0,
+                       NumMessages:   2,
+                       NumExtensions: 0,
+                       NumServices:   1,
+               },
+               GoTypes:           file_proto_greet_proto_goTypes,
+               DependencyIndexes: file_proto_greet_proto_depIdxs,
+               MessageInfos:      file_proto_greet_proto_msgTypes,
+       }.Build()
+       File_proto_greet_proto = out.File
+       file_proto_greet_proto_rawDesc = nil
+       file_proto_greet_proto_goTypes = nil
+       file_proto_greet_proto_depIdxs = nil
+}
diff --git a/router/tag/proto/greet.proto b/router/tag/proto/greet.proto
new file mode 100644
index 00000000..47da7072
--- /dev/null
+++ b/router/tag/proto/greet.proto
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+package greet;
+
+option go_package = 
"github.com/apache/dubbo-go-samples/router/tag/proto;greet";
+
+message GreetRequest {
+  string name = 1;
+}
+
+message GreetResponse {
+  string greeting = 1;
+}
+
+service GreetService {
+  rpc Greet(GreetRequest) returns (GreetResponse);
+}
diff --git a/router/tag/proto/greet.triple.go b/router/tag/proto/greet.triple.go
new file mode 100644
index 00000000..1df73466
--- /dev/null
+++ b/router/tag/proto/greet.triple.go
@@ -0,0 +1,122 @@
+// Code generated by protoc-gen-triple. DO NOT EDIT.
+//
+// Source: proto/greet.proto
+package greet
+
+import (
+       "context"
+)
+
+import (
+       "dubbo.apache.org/dubbo-go/v3"
+       "dubbo.apache.org/dubbo-go/v3/client"
+       "dubbo.apache.org/dubbo-go/v3/common"
+       "dubbo.apache.org/dubbo-go/v3/common/constant"
+       "dubbo.apache.org/dubbo-go/v3/protocol/triple/triple_protocol"
+       "dubbo.apache.org/dubbo-go/v3/server"
+)
+
+// This is a compile-time assertion to ensure that this generated file and the 
Triple package
+// are compatible. If you get a compiler error that this constant is not 
defined, this code was
+// generated with a version of Triple newer than the one compiled into your 
binary. You can fix the
+// problem by either regenerating this code with an older version of Triple or 
updating the Triple
+// version compiled into your binary.
+const _ = triple_protocol.IsAtLeastVersion0_1_0
+
+const (
+       // GreetServiceName is the fully-qualified name of the GreetService 
service.
+       GreetServiceName = "greet.GreetService"
+)
+
+// These constants are the fully-qualified names of the RPCs defined in this 
package. They're
+// exposed at runtime as procedure and as the final two segments of the HTTP 
route.
+//
+// Note that these are different from the fully-qualified method names used by
+// google.golang.org/protobuf/reflect/protoreflect. To convert from these 
constants to
+// reflection-formatted method names, remove the leading slash and convert the 
remaining slash to a
+// period.
+const (
+       // GreetServiceGreetProcedure is the fully-qualified name of the 
GreetService's Greet RPC.
+       GreetServiceGreetProcedure = "/greet.GreetService/Greet"
+)
+
+var (
+       _ GreetService = (*GreetServiceImpl)(nil)
+)
+
+// GreetService is a client for the greet.GreetService service.
+type GreetService interface {
+       Greet(ctx context.Context, req *GreetRequest, opts 
...client.CallOption) (*GreetResponse, error)
+}
+
+// NewGreetService constructs a client for the greet.GreetService service.
+func NewGreetService(cli *client.Client, opts ...client.ReferenceOption) 
(GreetService, error) {
+       conn, err := cli.DialWithInfo("greet.GreetService", 
&GreetService_ClientInfo, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return &GreetServiceImpl{
+               conn: conn,
+       }, nil
+}
+
+func SetConsumerGreetService(srv common.RPCService) {
+       dubbo.SetConsumerServiceWithInfo(srv, &GreetService_ClientInfo)
+}
+
+// GreetServiceImpl implements GreetService.
+type GreetServiceImpl struct {
+       conn *client.Connection
+}
+
+func (c *GreetServiceImpl) Greet(ctx context.Context, req *GreetRequest, opts 
...client.CallOption) (*GreetResponse, error) {
+       resp := new(GreetResponse)
+       if err := c.conn.CallUnary(ctx, []interface{}{req}, resp, "Greet", 
opts...); err != nil {
+               return nil, err
+       }
+       return resp, nil
+}
+
+var GreetService_ClientInfo = client.ClientInfo{
+       InterfaceName: "greet.GreetService",
+       MethodNames:   []string{"Greet"},
+       ConnectionInjectFunc: func(dubboCliRaw interface{}, conn 
*client.Connection) {
+               dubboCli := dubboCliRaw.(*GreetServiceImpl)
+               dubboCli.conn = conn
+       },
+}
+
+// GreetServiceHandler is an implementation of the greet.GreetService service.
+type GreetServiceHandler interface {
+       Greet(context.Context, *GreetRequest) (*GreetResponse, error)
+}
+
+func RegisterGreetServiceHandler(srv *server.Server, hdlr GreetServiceHandler, 
opts ...server.ServiceOption) error {
+       return srv.Register(hdlr, &GreetService_ServiceInfo, opts...)
+}
+
+func SetProviderGreetService(srv common.RPCService) {
+       dubbo.SetProviderServiceWithInfo(srv, &GreetService_ServiceInfo)
+}
+
+var GreetService_ServiceInfo = server.ServiceInfo{
+       InterfaceName: "greet.GreetService",
+       ServiceType:   (*GreetServiceHandler)(nil),
+       Methods: []server.MethodInfo{
+               {
+                       Name: "Greet",
+                       Type: constant.CallUnary,
+                       ReqInitFunc: func() interface{} {
+                               return new(GreetRequest)
+                       },
+                       MethodFunc: func(ctx context.Context, args 
[]interface{}, handler interface{}) (interface{}, error) {
+                               req := args[0].(*GreetRequest)
+                               res, err := 
handler.(GreetServiceHandler).Greet(ctx, req)
+                               if err != nil {
+                                       return nil, err
+                               }
+                               return triple_protocol.NewResponse(res), nil
+                       },
+               },
+       },
+}
diff --git a/start_integrate_test.sh b/start_integrate_test.sh
index e46dba82..c35db120 100755
--- a/start_integrate_test.sh
+++ b/start_integrate_test.sh
@@ -88,6 +88,9 @@ array+=("java_interop/protobuf-triple")
 array+=("java_interop/service_discovery/interface")
 array+=("java_interop/service_discovery/service")
 
+# router
+array+=("router/tag")
+
 DOCKER_DIR="$(pwd)"
 DOCKER_COMPOSE_CMD="docker-compose"
 

Reply via email to