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

liujun pushed a commit to branch feature-triple
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/feature-triple by this push:
     new 38e57c78e feat: copy bare configurations from config to global (#2413)
38e57c78e is described below

commit 38e57c78e2f1de2ff4f0088f3662413205515f71
Author: Scout Wang <[email protected]>
AuthorDate: Sat Sep 2 10:52:16 2023 +0800

    feat: copy bare configurations from config to global (#2413)
---
 client/client.go                                   |  56 ++++++++++
 client/compat.go                                   |  21 +++-
 client/options.go                                  | 104 +++++++++++++++++-
 client/reference_config.go                         |   3 +-
 compat.go                                          |  29 ++---
 {config_center => global}/config_center_config.go  |  28 +++--
 .../report => global}/metadata_report_config.go    |  16 +--
 global/method_config.go                            |  18 +++
 {metrics => global}/metric_config.go               |  18 +--
 {protocol => global}/protocol_config.go            |  14 +--
 global/reference_config.go                         |  36 ++++++
 {registry => global}/registry_config.go            |  34 +++---
 options.go                                         |  74 ++++++-------
 protocol/triple/internal/client/cmd/main.go        | 122 ---------------------
 .../client/{cmd => cmd_classic}/dubbogo.yml        |   0
 .../triple/internal/client/cmd_classic/main.go     |  28 +++++
 protocol/triple/internal/client/cmd_client/main.go |  30 +++++
 .../triple/internal/client/cmd_instance/main.go    |  49 +++++++++
 18 files changed, 438 insertions(+), 242 deletions(-)

diff --git a/client/client.go b/client/client.go
index ab93c373a..13334b0bc 100644
--- a/client/client.go
+++ b/client/client.go
@@ -19,6 +19,9 @@ package client
 
 import (
        "context"
+       commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
+       "dubbo.apache.org/dubbo-go/v3/config"
+       "dubbo.apache.org/dubbo-go/v3/global"
 )
 
 import (
@@ -35,6 +38,8 @@ type Client struct {
        invoker protocol.Invoker
        info    *ClientInfo
        cfg     *ReferenceConfig
+
+       cliOpts *ClientOptions
 }
 
 type ClientInfo struct {
@@ -44,6 +49,57 @@ type ClientInfo struct {
        Meta             map[string]interface{}
 }
 
+func (cli *Client) init(opts ...global.ReferenceOption) error {
+       refCfg := global.DefaultReferenceConfig()
+       for _, opt := range opts {
+               opt(refCfg)
+       }
+
+       // init method
+       if length := len(refCfg.Methods); length > 0 {
+               cli.methodsCompat = make([]*config.MethodConfig, length)
+               for i, method := range refCfg.Methods {
+                       cli.methodsCompat[i] = compatMethodConfig(method)
+                       if err := cli.methodsCompat[i].Init(); err != nil {
+                               return err
+                       }
+               }
+
+       }
+       // init application
+       if refCfg.pplication != nil {
+               rc.applicationCompat = compatApplicationConfig(rc.application)
+               if err := rc.applicationCompat.Init(); err != nil {
+                       return err
+               }
+               rc.metaDataType = rc.applicationCompat.MetadataType
+               if rc.Group == "" {
+                       rc.Group = rc.applicationCompat.Group
+               }
+               if rc.Version == "" {
+                       rc.Version = rc.applicationCompat.Version
+               }
+       }
+       // init cluster
+       if rc.Cluster == "" {
+               rc.Cluster = "failover"
+       }
+       // todo: move to registry package
+       // init registries
+       if rc.registries != nil {
+               rc.registriesCompat = make(map[string]*config.RegistryConfig)
+               for key, reg := range rc.registries {
+                       rc.registriesCompat[key] = compatRegistryConfig(reg)
+                       if err := rc.registriesCompat[key].Init(); err != nil {
+                               return err
+                       }
+               }
+       }
+       rc.RegistryIDs = commonCfg.TranslateIds(rc.RegistryIDs)
+
+       return commonCfg.Verify(rc)
+}
+
 func (cli *Client) call(ctx context.Context, paramsRawVals []interface{}, 
interfaceName, methodName, callType string, opts ...CallOption) 
(protocol.Result, error) {
        // get a default CallOptions
        // apply CallOption
diff --git a/client/compat.go b/client/compat.go
index f09ddb61d..b1f8d3895 100644
--- a/client/compat.go
+++ b/client/compat.go
@@ -20,7 +20,6 @@ package client
 import (
        "dubbo.apache.org/dubbo-go/v3/config"
        "dubbo.apache.org/dubbo-go/v3/global"
-       "dubbo.apache.org/dubbo-go/v3/registry"
 )
 
 // these functions are used to resolve circular dependencies temporarily.
@@ -40,7 +39,7 @@ func compatApplicationConfig(c *global.ApplicationConfig) 
*config.ApplicationCon
        }
 }
 
-func compatRegistryConfig(c *registry.RegistryConfig) *config.RegistryConfig {
+func compatRegistryConfig(c *global.RegistryConfig) *config.RegistryConfig {
        return &config.RegistryConfig{
                Protocol:          c.Protocol,
                Timeout:           c.Timeout,
@@ -60,3 +59,21 @@ func compatRegistryConfig(c *registry.RegistryConfig) 
*config.RegistryConfig {
                UseAsConfigCenter: c.UseAsConfigCenter,
        }
 }
+
+func compatMethodConfig(c *global.MethodConfig) *config.MethodConfig {
+       return &config.MethodConfig{
+               InterfaceId:                 c.InterfaceId,
+               InterfaceName:               c.InterfaceName,
+               Name:                        c.Name,
+               Retries:                     c.Retries,
+               LoadBalance:                 c.LoadBalance,
+               Weight:                      c.Weight,
+               TpsLimitInterval:            c.TpsLimitInterval,
+               TpsLimitRate:                c.TpsLimitRate,
+               TpsLimitStrategy:            c.TpsLimitStrategy,
+               ExecuteLimit:                c.ExecuteLimit,
+               ExecuteLimitRejectedHandler: c.ExecuteLimitRejectedHandler,
+               Sticky:                      c.Sticky,
+               RequestTimeout:              c.RequestTimeout,
+       }
+}
diff --git a/client/options.go b/client/options.go
index 19063e8c7..6e3cffd84 100644
--- a/client/options.go
+++ b/client/options.go
@@ -18,13 +18,109 @@
 package client
 
 import (
+       "dubbo.apache.org/dubbo-go/v3/common"
+       commonCfg "dubbo.apache.org/dubbo-go/v3/common/config"
+       "dubbo.apache.org/dubbo-go/v3/config"
        "dubbo.apache.org/dubbo-go/v3/global"
+       "dubbo.apache.org/dubbo-go/v3/protocol"
+       "dubbo.apache.org/dubbo-go/v3/proxy"
+       "github.com/creasty/defaults"
        "strconv"
 )
 
-import (
-       "dubbo.apache.org/dubbo-go/v3/registry"
-)
+type ClientOptions struct {
+       Application *global.ApplicationConfig
+       Consumer    *global.ConsumerConfig
+       Reference   *global.ReferenceConfig
+       Registries  map[string]*global.RegistryConfig
+
+       pxy          *proxy.Proxy
+       id           string
+       invoker      protocol.Invoker
+       urls         []*common.URL
+       metaDataType string
+       info         *ClientInfo
+
+       methodsCompat []*config.MethodConfig
+}
+
+func (cliOpts *ClientOptions) init() error {
+       if err := defaults.Set(cliOpts); err != nil {
+               return err
+       }
+
+       // init method
+       methods := cliOpts.Reference.Methods
+       if length := len(methods); length > 0 {
+               cliOpts.methodsCompat = make([]*config.MethodConfig, length)
+               for i, method := range methods {
+                       cliOpts.methodsCompat[i] = compatMethodConfig(method)
+                       if err := cliOpts.methodsCompat[i].Init(); err != nil {
+                               return err
+                       }
+               }
+
+       }
+
+       // init application
+       if rc.application != nil {
+               rc.applicationCompat = compatApplicationConfig(rc.application)
+               if err := rc.applicationCompat.Init(); err != nil {
+                       return err
+               }
+               rc.metaDataType = rc.applicationCompat.MetadataType
+               if rc.Group == "" {
+                       rc.Group = rc.applicationCompat.Group
+               }
+               if rc.Version == "" {
+                       rc.Version = rc.applicationCompat.Version
+               }
+       }
+       // init cluster
+       if rc.Cluster == "" {
+               rc.Cluster = "failover"
+       }
+       // todo: move to registry package
+       // init registries
+       if rc.registries != nil {
+               rc.registriesCompat = make(map[string]*config.RegistryConfig)
+               for key, reg := range rc.registries {
+                       rc.registriesCompat[key] = compatRegistryConfig(reg)
+                       if err := rc.registriesCompat[key].Init(); err != nil {
+                               return err
+                       }
+               }
+       }
+       rc.RegistryIDs = commonCfg.TranslateIds(rc.RegistryIDs)
+
+       return commonCfg.Verify(rc)
+}
+
+type ClientOption func(*ClientOptions)
+
+func WithApplication(application *global.ApplicationConfig) ClientOption {
+       return func(opts *ClientOptions) {
+               opts.Application = application
+       }
+}
+
+func WithConsumer(consumer *global.ConsumerConfig) ClientOption {
+       return func(opts *ClientOptions) {
+               opts.Consumer = consumer
+       }
+}
+
+func WithReference(reference *global.ReferenceConfig) ClientOption {
+       return func(opts *ClientOptions) {
+               opts.Reference = reference
+       }
+}
+
+func WithRegistries(registries map[string]*global.RegistryConfig) ClientOption 
{
+       return func(opts *ClientOptions) {
+               opts.Registries = registries
+       }
+}
 
 // todo: need to be consistent with MethodConfig
 type CallOptions struct {
@@ -218,7 +314,7 @@ func WithProxyFactory(proxyFactory string) ReferenceOption {
 
 // ----------From RegistryConfig----------
 
-func WithRegistries(registries map[string]*registry.RegistryConfig) 
ReferenceOption {
+func WithRegistries(registries map[string]*global.RegistryConfig) 
ReferenceOption {
        return func(cfg *ReferenceConfig) {
                cfg.registries = registries
        }
diff --git a/client/reference_config.go b/client/reference_config.go
index 2d53ff556..0d024661f 100644
--- a/client/reference_config.go
+++ b/client/reference_config.go
@@ -45,7 +45,6 @@ import (
        "dubbo.apache.org/dubbo-go/v3/protocol"
        "dubbo.apache.org/dubbo-go/v3/protocol/protocolwrapper"
        "dubbo.apache.org/dubbo-go/v3/proxy"
-       "dubbo.apache.org/dubbo-go/v3/registry"
 )
 
 // ReferenceConfig is the configuration of service consumer
@@ -89,7 +88,7 @@ type ReferenceConfig struct {
        application       *global.ApplicationConfig
        applicationCompat *config.ApplicationConfig
 
-       registries       map[string]*registry.RegistryConfig
+       registries       map[string]*global.RegistryConfig
        registriesCompat map[string]*config.RegistryConfig
 }
 
diff --git a/compat.go b/compat.go
index 30bca719b..65d68f517 100644
--- a/compat.go
+++ b/compat.go
@@ -19,12 +19,7 @@ package dubbo
 
 import (
        "dubbo.apache.org/dubbo-go/v3/config"
-       "dubbo.apache.org/dubbo-go/v3/config_center"
        "dubbo.apache.org/dubbo-go/v3/global"
-       "dubbo.apache.org/dubbo-go/v3/metadata/report"
-       "dubbo.apache.org/dubbo-go/v3/metrics"
-       "dubbo.apache.org/dubbo-go/v3/protocol"
-       "dubbo.apache.org/dubbo-go/v3/registry"
        "go.uber.org/atomic"
 )
 
@@ -78,7 +73,7 @@ func compatApplicationConfig(c *global.ApplicationConfig) 
*config.ApplicationCon
        }
 }
 
-func compatProtocolConfig(c *protocol.ProtocolConfig) *config.ProtocolConfig {
+func compatProtocolConfig(c *global.ProtocolConfig) *config.ProtocolConfig {
        return &config.ProtocolConfig{
                Name:                 c.Name,
                Ip:                   c.Ip,
@@ -89,7 +84,7 @@ func compatProtocolConfig(c *protocol.ProtocolConfig) 
*config.ProtocolConfig {
        }
 }
 
-func compatRegistryConfig(c *registry.RegistryConfig) *config.RegistryConfig {
+func compatRegistryConfig(c *global.RegistryConfig) *config.RegistryConfig {
        return &config.RegistryConfig{
                Protocol:          c.Protocol,
                Timeout:           c.Timeout,
@@ -110,7 +105,7 @@ func compatRegistryConfig(c *registry.RegistryConfig) 
*config.RegistryConfig {
        }
 }
 
-func compatCenterConfig(c *config_center.CenterConfig) *config.CenterConfig {
+func compatCenterConfig(c *global.CenterConfig) *config.CenterConfig {
        return &config.CenterConfig{
                Protocol:      c.Protocol,
                Address:       c.Address,
@@ -127,7 +122,7 @@ func compatCenterConfig(c *config_center.CenterConfig) 
*config.CenterConfig {
        }
 }
 
-func compatMetadataReportConfig(c *report.MetadataReportConfig) 
*config.MetadataReportConfig {
+func compatMetadataReportConfig(c *global.MetadataReportConfig) 
*config.MetadataReportConfig {
        return &config.MetadataReportConfig{
                Protocol:  c.Protocol,
                Address:   c.Address,
@@ -156,13 +151,13 @@ func compatProviderConfig(c *global.ProviderConfig) 
*config.ProviderConfig {
 
 func compatConsumerConfig(c *global.ConsumerConfig) *config.ConsumerConfig {
        return &config.ConsumerConfig{
-               Filter:          c.Filter,
-               RegistryIDs:     c.RegistryIDs,
-               Protocol:        c.Protocol,
-               RequestTimeout:  c.RequestTimeout,
-               ProxyFactory:    c.ProxyFactory,
-               Check:           c.Check,
-               AdaptiveService: c.AdaptiveService,
+               Filter:                         c.Filter,
+               RegistryIDs:                    c.RegistryIDs,
+               Protocol:                       c.Protocol,
+               RequestTimeout:                 c.RequestTimeout,
+               ProxyFactory:                   c.ProxyFactory,
+               Check:                          c.Check,
+               AdaptiveService:                c.AdaptiveService,
                TracingKey:                     c.TracingKey,
                FilterConf:                     c.FilterConf,
                MaxWaitTimeForServiceDiscovery: 
c.MaxWaitTimeForServiceDiscovery,
@@ -170,7 +165,7 @@ func compatConsumerConfig(c *global.ConsumerConfig) 
*config.ConsumerConfig {
        }
 }
 
-func compatMetricConfig(c *metrics.MetricConfig) *config.MetricConfig {
+func compatMetricConfig(c *global.MetricConfig) *config.MetricConfig {
        return &config.MetricConfig{
                Mode:               c.Mode,
                Namespace:          c.Namespace,
diff --git a/config_center/config_center_config.go 
b/global/config_center_config.go
similarity index 77%
rename from config_center/config_center_config.go
rename to global/config_center_config.go
index 8d5ee82f5..d219b693a 100644
--- a/config_center/config_center_config.go
+++ b/global/config_center_config.go
@@ -1,4 +1,4 @@
-package config_center
+package global
 
 // CenterConfig is configuration for config center
 //
@@ -32,69 +32,67 @@ func DefaultCenterConfig() *CenterConfig {
 
 type CenterOption func(*CenterConfig)
 
-func WithProtocol(protocol string) CenterOption {
+func WithCenter_Protocol(protocol string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Protocol = protocol
        }
 }
 
-func WithAddress(address string) CenterOption {
+func WithCenter_Address(address string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Address = address
        }
 }
 
-func WithDataID(id string) CenterOption {
+func WithCenter_DataID(id string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.DataId = id
        }
 }
 
-func WithCluster(cluster string) CenterOption {
+func WithCenter_Cluster(cluster string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Cluster = cluster
        }
 }
 
-// todo: think about changing the name of another WithGroup in this package
-func WithGroup_(group string) CenterOption {
+func WithCenter_Group(group string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Group = group
        }
 }
 
-func WithUsername(name string) CenterOption {
+func WithCenter_Username(name string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Username = name
        }
 }
 
-func WithPassword(password string) CenterOption {
+func WithCenter_Password(password string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Password = password
        }
 }
 
-func WithNamespace(namespace string) CenterOption {
+func WithCenter_Namespace(namespace string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Namespace = namespace
        }
 }
 
-func WithAppID(id string) CenterOption {
+func WithCenter_AppID(id string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.AppID = id
        }
 }
 
-// todo: think about changing the name of another WithTimeout in this package
-func WithTimeout_(timeout string) CenterOption {
+func WithCenter_Timeout(timeout string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.Timeout = timeout
        }
 }
 
-func WithParams(params map[string]string) CenterOption {
+func WithCenter_Params(params map[string]string) CenterOption {
        return func(cfg *CenterConfig) {
                if cfg.Params == nil {
                        cfg.Params = make(map[string]string)
@@ -105,7 +103,7 @@ func WithParams(params map[string]string) CenterOption {
        }
 }
 
-func WithFileExtension(extension string) CenterOption {
+func WithCenter_FileExtension(extension string) CenterOption {
        return func(cfg *CenterConfig) {
                cfg.FileExtension = extension
        }
diff --git a/metadata/report/metadata_report_config.go 
b/global/metadata_report_config.go
similarity index 81%
rename from metadata/report/metadata_report_config.go
rename to global/metadata_report_config.go
index 1531605ab..65c97f6d1 100644
--- a/metadata/report/metadata_report_config.go
+++ b/global/metadata_report_config.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package report
+package global
 
 // MetadataReportConfig is app level configuration
 type MetadataReportConfig struct {
@@ -37,43 +37,43 @@ func DefaultMetadataReportConfig() *MetadataReportConfig {
 
 type MetadataReportOption func(*MetadataReportConfig)
 
-func WithProtocol(protocol string) MetadataReportOption {
+func WithMetadataReport_Protocol(protocol string) MetadataReportOption {
        return func(cfg *MetadataReportConfig) {
                cfg.Protocol = protocol
        }
 }
 
-func WithAddress(address string) MetadataReportOption {
+func WithMetadataReport_Address(address string) MetadataReportOption {
        return func(cfg *MetadataReportConfig) {
                cfg.Address = address
        }
 }
 
-func WithUsername(username string) MetadataReportOption {
+func WithMetadataReport_Username(username string) MetadataReportOption {
        return func(cfg *MetadataReportConfig) {
                cfg.Username = username
        }
 }
 
-func WithPassword(password string) MetadataReportOption {
+func WithMetadataReport_Password(password string) MetadataReportOption {
        return func(cfg *MetadataReportConfig) {
                cfg.Password = password
        }
 }
 
-func WithTimeout(timeout string) MetadataReportOption {
+func WithMetadataReport_Timeout(timeout string) MetadataReportOption {
        return func(cfg *MetadataReportConfig) {
                cfg.Timeout = timeout
        }
 }
 
-func WithGroup(group string) MetadataReportOption {
+func WithMetadataReport_Group(group string) MetadataReportOption {
        return func(cfg *MetadataReportConfig) {
                cfg.Group = group
        }
 }
 
-func WithNamespace(namespace string) MetadataReportOption {
+func WithMetadataReport_Namespace(namespace string) MetadataReportOption {
        return func(cfg *MetadataReportConfig) {
                cfg.Namespace = namespace
        }
diff --git a/global/method_config.go b/global/method_config.go
new file mode 100644
index 000000000..2090a3ef6
--- /dev/null
+++ b/global/method_config.go
@@ -0,0 +1,18 @@
+package global
+
+// MethodConfig defines method config
+type MethodConfig struct {
+       InterfaceId                 string
+       InterfaceName               string
+       Name                        string `yaml:"name"  json:"name,omitempty" 
property:"name"`
+       Retries                     string `yaml:"retries"  
json:"retries,omitempty" property:"retries"`
+       LoadBalance                 string `yaml:"loadbalance"  
json:"loadbalance,omitempty" property:"loadbalance"`
+       Weight                      int64  `yaml:"weight"  
json:"weight,omitempty" property:"weight"`
+       TpsLimitInterval            string `yaml:"tps.limit.interval" 
json:"tps.limit.interval,omitempty" property:"tps.limit.interval"`
+       TpsLimitRate                string `yaml:"tps.limit.rate" 
json:"tps.limit.rate,omitempty" property:"tps.limit.rate"`
+       TpsLimitStrategy            string `yaml:"tps.limit.strategy" 
json:"tps.limit.strategy,omitempty" property:"tps.limit.strategy"`
+       ExecuteLimit                string `yaml:"execute.limit" 
json:"execute.limit,omitempty" property:"execute.limit"`
+       ExecuteLimitRejectedHandler string 
`yaml:"execute.limit.rejected.handler" 
json:"execute.limit.rejected.handler,omitempty" 
property:"execute.limit.rejected.handler"`
+       Sticky                      bool   `yaml:"sticky"   
json:"sticky,omitempty" property:"sticky"`
+       RequestTimeout              string `yaml:"timeout"  
json:"timeout,omitempty" property:"timeout"`
+}
diff --git a/metrics/metric_config.go b/global/metric_config.go
similarity index 84%
rename from metrics/metric_config.go
rename to global/metric_config.go
index 03e7ff7d0..17df20aa9 100644
--- a/metrics/metric_config.go
+++ b/global/metric_config.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package metrics
+package global
 
 // MetricConfig This is the config struct for all metrics implementation
 type MetricConfig struct {
@@ -36,49 +36,49 @@ func DefaultMetricConfig() *MetricConfig {
 
 type MetricOption func(*MetricConfig)
 
-func WithMode(mode string) MetricOption {
+func WithMetric_Mode(mode string) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.Mode = mode
        }
 }
 
-func WithNamespace(namespace string) MetricOption {
+func WithMetric_Namespace(namespace string) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.Namespace = namespace
        }
 }
 
-func WithEnable(enable bool) MetricOption {
+func WithMetric_Enable(enable bool) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.Enable = &enable
        }
 }
 
-func WithPort(port string) MetricOption {
+func WithMetric_Port(port string) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.Port = port
        }
 }
 
-func WithPath(path string) MetricOption {
+func WithMetric_Path(path string) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.Path = path
        }
 }
 
-func WithPushGatewayAddress(address string) MetricOption {
+func WithMetric_PushGatewayAddress(address string) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.PushGatewayAddress = address
        }
 }
 
-func WithSummaryMaxAge(age int64) MetricOption {
+func WithMetric_SummaryMaxAge(age int64) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.SummaryMaxAge = age
        }
 }
 
-func WithProtocol(protocol string) MetricOption {
+func WithMetric_Protocol(protocol string) MetricOption {
        return func(cfg *MetricConfig) {
                cfg.Protocol = protocol
        }
diff --git a/protocol/protocol_config.go b/global/protocol_config.go
similarity index 85%
rename from protocol/protocol_config.go
rename to global/protocol_config.go
index 6b39061e9..2872c5b06 100644
--- a/protocol/protocol_config.go
+++ b/global/protocol_config.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package protocol
+package global
 
 // ProtocolConfig is protocol configuration
 type ProtocolConfig struct {
@@ -33,37 +33,37 @@ type ProtocolConfig struct {
 
 type ProtocolOption func(*ProtocolConfig)
 
-func WithName(name string) ProtocolOption {
+func WithProtocol_Name(name string) ProtocolOption {
        return func(cfg *ProtocolConfig) {
                cfg.Name = name
        }
 }
 
-func WithIp(ip string) ProtocolOption {
+func WithProtocol_Ip(ip string) ProtocolOption {
        return func(cfg *ProtocolConfig) {
                cfg.Ip = ip
        }
 }
 
-func WithPort(port string) ProtocolOption {
+func WithProtocol_Port(port string) ProtocolOption {
        return func(cfg *ProtocolConfig) {
                cfg.Port = port
        }
 }
 
-func WithParam(param interface{}) ProtocolOption {
+func WithProtocol_Param(param interface{}) ProtocolOption {
        return func(cfg *ProtocolConfig) {
                cfg.Params = param
        }
 }
 
-func WithMaxServerSendMsgSize(size string) ProtocolOption {
+func WithProtocol_MaxServerSendMsgSize(size string) ProtocolOption {
        return func(cfg *ProtocolConfig) {
                cfg.MaxServerSendMsgSize = size
        }
 }
 
-func WithMaxServerRecvMsgSize(size string) ProtocolOption {
+func WithProtocol_MaxServerRecvMsgSize(size string) ProtocolOption {
        return func(cfg *ProtocolConfig) {
                cfg.MaxServerRecvMsgSize = size
        }
diff --git a/global/reference_config.go b/global/reference_config.go
new file mode 100644
index 000000000..c1e2742fd
--- /dev/null
+++ b/global/reference_config.go
@@ -0,0 +1,36 @@
+package global
+
+// ReferenceConfig is the configuration of service consumer
+type ReferenceConfig struct {
+       InterfaceName    string            `yaml:"interface"  
json:"interface,omitempty" property:"interface"`
+       Check            *bool             `yaml:"check"  
json:"check,omitempty" property:"check"`
+       URL              string            `yaml:"url"  json:"url,omitempty" 
property:"url"`
+       Filter           string            `yaml:"filter" 
json:"filter,omitempty" property:"filter"`
+       Protocol         string            `yaml:"protocol"  
json:"protocol,omitempty" property:"protocol"`
+       RegistryIDs      []string          `yaml:"registry-ids"  
json:"registry-ids,omitempty"  property:"registry-ids"`
+       Cluster          string            `yaml:"cluster"  
json:"cluster,omitempty" property:"cluster"`
+       Loadbalance      string            `yaml:"loadbalance"  
json:"loadbalance,omitempty" property:"loadbalance"`
+       Retries          string            `yaml:"retries"  
json:"retries,omitempty" property:"retries"`
+       Group            string            `yaml:"group"  
json:"group,omitempty" property:"group"`
+       Version          string            `yaml:"version"  
json:"version,omitempty" property:"version"`
+       Serialization    string            `yaml:"serialization" 
json:"serialization" property:"serialization"`
+       ProvidedBy       string            `yaml:"provided_by"  
json:"provided_by,omitempty" property:"provided_by"`
+       Methods          []*MethodConfig   `yaml:"methods"  
json:"methods,omitempty" property:"methods"`
+       Async            bool              `yaml:"async"  
json:"async,omitempty" property:"async"`
+       Params           map[string]string `yaml:"params"  
json:"params,omitempty" property:"params"`
+       Generic          string            `yaml:"generic"  
json:"generic,omitempty" property:"generic"`
+       Sticky           bool              `yaml:"sticky"   
json:"sticky,omitempty" property:"sticky"`
+       RequestTimeout   string            `yaml:"timeout"  
json:"timeout,omitempty" property:"timeout"`
+       ForceTag         bool              `yaml:"force.tag"  
json:"force.tag,omitempty" property:"force.tag"`
+       TracingKey       string            `yaml:"tracing-key" 
json:"tracing-key,omitempty" propertiy:"tracing-key"`
+       MeshProviderPort int               `yaml:"mesh-provider-port" 
json:"mesh-provider-port,omitempty" propertiy:"mesh-provider-port"`
+}
+
+type ReferenceOption func(*ReferenceConfig)
+
+func DefaultReferenceConfig() *ReferenceConfig {
+       return &ReferenceConfig{
+               Methods: make([]*MethodConfig, 0, 8),
+               Params:  make(map[string]string, 8),
+       }
+}
diff --git a/registry/registry_config.go b/global/registry_config.go
similarity index 81%
rename from registry/registry_config.go
rename to global/registry_config.go
index 468c1fe51..7330ef2a9 100644
--- a/registry/registry_config.go
+++ b/global/registry_config.go
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package registry
+package global
 
 // todo(DMwangnima): finish refactoring and move related logic from config 
package to this file.
 // This RegistryConfig is a copy of /config/RegistryConfig right now.
@@ -43,97 +43,97 @@ type RegistryConfig struct {
 
 type RegistryOption func(*RegistryConfig)
 
-func WithProtocol(protocol string) RegistryOption {
+func WithRegistry_Protocol(protocol string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Protocol = protocol
        }
 }
 
-func WithTimeout(timeout string) RegistryOption {
+func WithRegistry_Timeout(timeout string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Timeout = timeout
        }
 }
 
-func WithGroup(group string) RegistryOption {
+func WithRegistry_Group(group string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Group = group
        }
 }
 
-func WithNamespace(namespace string) RegistryOption {
+func WithRegistry_Namespace(namespace string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Namespace = namespace
        }
 }
 
-func WithTTL(ttl string) RegistryOption {
+func WithRegistry_TTL(ttl string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.TTL = ttl
        }
 }
 
-func WithAddress(address string) RegistryOption {
+func WithRegistry_Address(address string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Address = address
        }
 }
 
-func WithUsername(name string) RegistryOption {
+func WithRegistry_Username(name string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Username = name
        }
 }
 
-func WithPassword(password string) RegistryOption {
+func WithRegistry_Password(password string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Password = password
        }
 }
 
-func WithSimplified(flag bool) RegistryOption {
+func WithRegistry_Simplified(flag bool) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Simplified = flag
        }
 }
 
-func WithPreferred(flag bool) RegistryOption {
+func WithRegistry_Preferred(flag bool) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Preferred = flag
        }
 }
 
-func WithZone(zone string) RegistryOption {
+func WithRegistry_Zone(zone string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Zone = zone
        }
 }
 
-func WithWeight(weight int64) RegistryOption {
+func WithRegistry_Weight(weight int64) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Weight = weight
        }
 }
 
-func WithParams(params map[string]string) RegistryOption {
+func WithRegistry_Params(params map[string]string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.Params = params
        }
 }
 
-func WithRegistryType(typ string) RegistryOption {
+func WithRegistry_RegistryType(typ string) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.RegistryType = typ
        }
 }
 
-func WithUseAsMetaReport(flag bool) RegistryOption {
+func WithRegistry_UseAsMetaReport(flag bool) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.UseAsMetaReport = flag
        }
 }
 
-func WithUseAsConfigCenter(flag bool) RegistryOption {
+func WithRegistry_UseAsConfigCenter(flag bool) RegistryOption {
        return func(cfg *RegistryConfig) {
                cfg.UseAsConfigCenter = flag
        }
diff --git a/options.go b/options.go
index 550a7c049..c920d8ed3 100644
--- a/options.go
+++ b/options.go
@@ -18,44 +18,40 @@
 package dubbo
 
 import (
-       "dubbo.apache.org/dubbo-go/v3/config_center"
        "dubbo.apache.org/dubbo-go/v3/global"
-       "dubbo.apache.org/dubbo-go/v3/metadata/report"
-       "dubbo.apache.org/dubbo-go/v3/metrics"
-       "dubbo.apache.org/dubbo-go/v3/protocol"
-       "dubbo.apache.org/dubbo-go/v3/registry"
 )
 
 type RootConfig struct {
-       Application         *global.ApplicationConfig           
`validate:"required" yaml:"application" json:"application,omitempty" 
property:"application"`
-       Protocols           map[string]*protocol.ProtocolConfig 
`validate:"required" yaml:"protocols" json:"protocols" property:"protocols"`
-       Registries          map[string]*registry.RegistryConfig 
`yaml:"registries" json:"registries" property:"registries"`
-       ConfigCenter        *config_center.CenterConfig         
`yaml:"config-center" json:"config-center,omitempty"`
-       MetadataReport      *report.MetadataReportConfig        
`yaml:"metadata-report" json:"metadata-report,omitempty" 
property:"metadata-report"`
-       Provider            *global.ProviderConfig              
`yaml:"provider" json:"provider" property:"provider"`
-       Consumer            *global.ConsumerConfig              
`yaml:"consumer" json:"consumer" property:"consumer"`
-       Metric              *metrics.MetricConfig               `yaml:"metrics" 
json:"metrics,omitempty" property:"metrics"`
-       Tracing             map[string]*global.TracingConfig    `yaml:"tracing" 
json:"tracing,omitempty" property:"tracing"`
-       Logger              *global.LoggerConfig                `yaml:"logger" 
json:"logger,omitempty" property:"logger"`
-       Shutdown            *global.ShutdownConfig              
`yaml:"shutdown" json:"shutdown,omitempty" property:"shutdown"`
-       Router              []*RouterConfig                     `yaml:"router" 
json:"router,omitempty" property:"router"`
-       EventDispatcherType string                              
`default:"direct" yaml:"event-dispatcher-type" 
json:"event-dispatcher-type,omitempty"`
-       CacheFile           string                              
`yaml:"cache_file" json:"cache_file,omitempty" property:"cache_file"`
-       Custom              *global.CustomConfig                `yaml:"custom" 
json:"custom,omitempty" property:"custom"`
-       Profiles            *global.ProfilesConfig              
`yaml:"profiles" json:"profiles,omitempty" property:"profiles"`
-       TLSConfig           *global.TLSConfig                   
`yaml:"tls_config" json:"tls_config,omitempty" property:"tls_config"`
+       Application    *global.ApplicationConfig         `validate:"required" 
yaml:"application" json:"application,omitempty" property:"application"`
+       Protocols      map[string]*global.ProtocolConfig `validate:"required" 
yaml:"protocols" json:"protocols" property:"protocols"`
+       Registries     map[string]*global.RegistryConfig `yaml:"registries" 
json:"registries" property:"registries"`
+       ConfigCenter   *global.CenterConfig              `yaml:"config-center" 
json:"config-center,omitempty"`
+       MetadataReport *global.MetadataReportConfig      
`yaml:"metadata-report" json:"metadata-report,omitempty" 
property:"metadata-report"`
+       Provider       *global.ProviderConfig            `yaml:"provider" 
json:"provider" property:"provider"`
+       Consumer       *global.ConsumerConfig            `yaml:"consumer" 
json:"consumer" property:"consumer"`
+       Metric         *global.MetricConfig              `yaml:"metrics" 
json:"metrics,omitempty" property:"metrics"`
+       Tracing        map[string]*global.TracingConfig  `yaml:"tracing" 
json:"tracing,omitempty" property:"tracing"`
+       Logger         *global.LoggerConfig              `yaml:"logger" 
json:"logger,omitempty" property:"logger"`
+       Shutdown       *global.ShutdownConfig            `yaml:"shutdown" 
json:"shutdown,omitempty" property:"shutdown"`
+       // todo(DMwangnima): router feature would be supported in the future
+       //Router              []*RouterConfig                   `yaml:"router" 
json:"router,omitempty" property:"router"`
+       EventDispatcherType string                 `default:"direct" 
yaml:"event-dispatcher-type" json:"event-dispatcher-type,omitempty"`
+       CacheFile           string                 `yaml:"cache_file" 
json:"cache_file,omitempty" property:"cache_file"`
+       Custom              *global.CustomConfig   `yaml:"custom" 
json:"custom,omitempty" property:"custom"`
+       Profiles            *global.ProfilesConfig `yaml:"profiles" 
json:"profiles,omitempty" property:"profiles"`
+       TLSConfig           *global.TLSConfig      `yaml:"tls_config" 
json:"tls_config,omitempty" property:"tls_config"`
 }
 
 func defaultRootConfig() *RootConfig {
        return &RootConfig{
                Application:    global.DefaultApplicationConfig(),
-               Protocols:      make(map[string]*protocol.ProtocolConfig),
-               Registries:     make(map[string]*registry.RegistryConfig),
-               ConfigCenter:   config_center.DefaultCenterConfig(),
-               MetadataReport: report.DefaultMetadataReportConfig(),
+               Protocols:      make(map[string]*global.ProtocolConfig),
+               Registries:     make(map[string]*global.RegistryConfig),
+               ConfigCenter:   global.DefaultCenterConfig(),
+               MetadataReport: global.DefaultMetadataReportConfig(),
                Provider:       global.DefaultProviderConfig(),
                Consumer:       global.DefaultConsumerConfig(),
-               Metric:         metrics.DefaultMetricConfig(),
+               Metric:         global.DefaultMetricConfig(),
                Tracing:        make(map[string]*global.TracingConfig),
                Logger:         global.DefaultLoggerConfig(),
                Shutdown:       global.DefaultShutdownConfig(),
@@ -91,36 +87,36 @@ func WithApplication(opts ...global.ApplicationOption) 
RootOption {
        }
 }
 
-func WithProtocol(key string, opts ...protocol.ProtocolOption) RootOption {
-       proCfg := new(protocol.ProtocolConfig)
+func WithProtocol(key string, opts ...global.ProtocolOption) RootOption {
+       proCfg := new(global.ProtocolConfig)
        for _, opt := range opts {
                opt(proCfg)
        }
 
        return func(cfg *RootConfig) {
                if cfg.Protocols == nil {
-                       cfg.Protocols = 
make(map[string]*protocol.ProtocolConfig)
+                       cfg.Protocols = make(map[string]*global.ProtocolConfig)
                }
                cfg.Protocols[key] = proCfg
        }
 }
 
-func WithRegistry(key string, opts ...registry.RegistryOption) RootOption {
-       regCfg := new(registry.RegistryConfig)
+func WithRegistry(key string, opts ...global.RegistryOption) RootOption {
+       regCfg := new(global.RegistryConfig)
        for _, opt := range opts {
                opt(regCfg)
        }
 
        return func(cfg *RootConfig) {
                if cfg.Registries == nil {
-                       cfg.Registries = 
make(map[string]*registry.RegistryConfig)
+                       cfg.Registries = make(map[string]*global.RegistryConfig)
                }
                cfg.Registries[key] = regCfg
        }
 }
 
-func WithConfigCenter(opts ...config_center.CenterOption) RootOption {
-       ccCfg := new(config_center.CenterConfig)
+func WithConfigCenter(opts ...global.CenterOption) RootOption {
+       ccCfg := new(global.CenterConfig)
        for _, opt := range opts {
                opt(ccCfg)
        }
@@ -130,8 +126,8 @@ func WithConfigCenter(opts ...config_center.CenterOption) 
RootOption {
        }
 }
 
-func WithMetadataReport(opts ...report.MetadataReportOption) RootOption {
-       mrCfg := new(report.MetadataReportConfig)
+func WithMetadataReport(opts ...global.MetadataReportOption) RootOption {
+       mrCfg := new(global.MetadataReportConfig)
        for _, opt := range opts {
                opt(mrCfg)
        }
@@ -152,8 +148,8 @@ func WithConsumer(opts ...global.ConsumerOption) RootOption 
{
        }
 }
 
-func WithMetric(opts ...metrics.MetricOption) RootOption {
-       meCfg := new(metrics.MetricConfig)
+func WithMetric(opts ...global.MetricOption) RootOption {
+       meCfg := new(global.MetricConfig)
        for _, opt := range opts {
                opt(meCfg)
        }
diff --git a/protocol/triple/internal/client/cmd/main.go 
b/protocol/triple/internal/client/cmd/main.go
deleted file mode 100644
index 55ede08d4..000000000
--- a/protocol/triple/internal/client/cmd/main.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package main
-
-import (
-       "context"
-)
-
-import (
-       "github.com/dubbogo/gost/log/logger"
-)
-
-import (
-       "dubbo.apache.org/dubbo-go/v3/client"
-       _ "dubbo.apache.org/dubbo-go/v3/imports"
-       greet "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
-       
"dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto/greettriple"
-)
-
-func main() {
-       //client initialization
-       cli, err := client.NewClient(
-               client.WithURL("127.0.0.1:8080"),
-       )
-       svc, err := greettriple.NewGreetService(cli)
-       if err != nil {
-               panic(err)
-       }
-
-       // classic config initialization
-       //svc := new(greettriple.GreetServiceImpl)
-       //greettriple.SetConsumerService(dubboCli)
-       //config.Load() // need dubbogo.yml
-
-       if err := testUnary(svc); err != nil {
-               logger.Error(err)
-               return
-       }
-
-       if err := testBidiStream(svc); err != nil {
-               logger.Error(err)
-               return
-       }
-
-       if err := testClientStream(svc); err != nil {
-               logger.Error(err)
-               return
-       }
-
-       if err := testServerStream(svc); err != nil {
-               logger.Error(err)
-               return
-       }
-}
-
-func testUnary(svc greettriple.GreetService) error {
-       logger.Info("start to test TRIPLE unary call")
-       resp, err := svc.Greet(context.Background(), &greet.GreetRequest{Name: 
"triple"})
-       if err != nil {
-               return err
-       }
-       logger.Infof("TRIPLE unary call resp: %s", resp.Greeting)
-       return nil
-}
-
-func testBidiStream(svc greettriple.GreetService) error {
-       logger.Info("start to test TRIPLE bidi stream")
-       stream, err := svc.GreetStream(context.Background())
-       if err != nil {
-               return err
-       }
-       if err := stream.Send(&greet.GreetStreamRequest{Name: "triple"}); err 
!= nil {
-               return err
-       }
-       resp, err := stream.Recv()
-       if err != nil {
-               return err
-       }
-       logger.Infof("TRIPLE bidi stream resp: %s", resp.Greeting)
-       if err := stream.CloseRequest(); err != nil {
-               return err
-       }
-       if err := stream.CloseResponse(); err != nil {
-               return err
-       }
-       return nil
-}
-
-func testClientStream(svc greettriple.GreetService) error {
-       logger.Info("start to test TRIPLE dubboClint stream")
-       stream, err := svc.GreetClientStream(context.Background())
-       if err != nil {
-               return err
-       }
-       for i := 0; i < 5; i++ {
-               if err := stream.Send(&greet.GreetClientStreamRequest{Name: 
"triple"}); err != nil {
-                       return err
-               }
-       }
-       resp, err := stream.CloseAndRecv()
-       if err != nil {
-               return err
-       }
-       logger.Infof("TRIPLE dubboClint stream resp: %s", resp.Greeting)
-       return nil
-}
-
-func testServerStream(svc greettriple.GreetService) error {
-       logger.Info("start to test TRIPLE server stream")
-       stream, err := svc.GreetServerStream(context.Background(), 
&greet.GreetServerStreamRequest{Name: "triple"})
-       if err != nil {
-               return err
-       }
-       for stream.Recv() {
-               logger.Infof("TRIPLE server stream resp: %s", 
stream.Msg().Greeting)
-       }
-       if stream.Err() != nil {
-               return err
-       }
-       if err := stream.Close(); err != nil {
-               return err
-       }
-       return nil
-}
diff --git a/protocol/triple/internal/client/cmd/dubbogo.yml 
b/protocol/triple/internal/client/cmd_classic/dubbogo.yml
similarity index 100%
rename from protocol/triple/internal/client/cmd/dubbogo.yml
rename to protocol/triple/internal/client/cmd_classic/dubbogo.yml
diff --git a/protocol/triple/internal/client/cmd_classic/main.go 
b/protocol/triple/internal/client/cmd_classic/main.go
new file mode 100644
index 000000000..a66b13c48
--- /dev/null
+++ b/protocol/triple/internal/client/cmd_classic/main.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+       "context"
+       "dubbo.apache.org/dubbo-go/v3/config"
+       "fmt"
+)
+
+import (
+       _ "dubbo.apache.org/dubbo-go/v3/imports"
+       greet "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
+       
"dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto/greettriple"
+)
+
+func main() {
+       svc := new(greettriple.GreetServiceImpl)
+       greettriple.SetConsumerService(svc)
+       if err := config.Load(); err != nil {
+               panic(err)
+       }
+
+       resp, err := svc.Greet(context.Background(), &greet.GreetRequest{Name: 
"dubbo"})
+       if err != nil {
+               panic(err)
+       }
+
+       fmt.Println(resp.Greeting)
+}
diff --git a/protocol/triple/internal/client/cmd_client/main.go 
b/protocol/triple/internal/client/cmd_client/main.go
new file mode 100644
index 000000000..2d2c4d982
--- /dev/null
+++ b/protocol/triple/internal/client/cmd_client/main.go
@@ -0,0 +1,30 @@
+package main
+
+import (
+       "context"
+       "dubbo.apache.org/dubbo-go/v3/client"
+       greet "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
+       
"dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto/greettriple"
+       "fmt"
+)
+
+func main() {
+       // for the most brief RPC case
+       cli, err := client.NewClient(
+               client.WithURL("127.0.0.1:20000"),
+       )
+       if err != nil {
+               panic(err)
+       }
+       svc, err := greettriple.NewGreetService(cli)
+       if err != nil {
+               panic(err)
+       }
+
+       resp, err := svc.Greet(context.Background(), &greet.GreetRequest{Name: 
"dubbo"})
+       if err != nil {
+               panic(err)
+       }
+
+       fmt.Println(resp.Greeting)
+}
diff --git a/protocol/triple/internal/client/cmd_instance/main.go 
b/protocol/triple/internal/client/cmd_instance/main.go
new file mode 100644
index 000000000..d0807c9cb
--- /dev/null
+++ b/protocol/triple/internal/client/cmd_instance/main.go
@@ -0,0 +1,49 @@
+package main
+
+import (
+       "context"
+       "dubbo.apache.org/dubbo-go/v3"
+       "dubbo.apache.org/dubbo-go/v3/client"
+       "dubbo.apache.org/dubbo-go/v3/global"
+       greet "dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto"
+       
"dubbo.apache.org/dubbo-go/v3/protocol/triple/internal/proto/greettriple"
+       "fmt"
+)
+
+func main() {
+       // global conception
+       // configure global configurations and common modules
+       ins, err := dubbo.NewInstance(
+               dubbo.WithApplication(
+                       global.WithApplication_Name("dubbo_test"),
+               ),
+               dubbo.WithRegistry("nacos",
+                       global.WithRegistry_Address("127.0.0.1:8848"),
+               ),
+               dubbo.WithMetric(
+                       global.WithMetric_Enable(true),
+               ),
+       )
+       if err != nil {
+               panic(err)
+       }
+       // configure the params that only client layer cares
+       cli, err := ins.NewClient(
+               client.WithRetries(3),
+       )
+       if err != nil {
+               panic(err)
+       }
+
+       svc, err := greettriple.NewGreetService(cli)
+       if err != nil {
+               panic(err)
+       }
+
+       resp, err := svc.Greet(context.Background(), &greet.GreetRequest{Name: 
"dubbo"})
+       if err != nil {
+               panic(err)
+       }
+
+       fmt.Println(resp.Greeting)
+}


Reply via email to