Files
gf/contrib/registry/consul/consul.go
hailaz ee24da4e72 refactor: interface{} to any and reflect.Ptr to reflect.Pointer (#4395)
This pull request standardizes the use of the Go 1.18+ `any` type alias
instead of `interface{}` throughout the codebase. The change improves
code readability and aligns with modern Go best practices. The update
touches many files, including core data structures, code generation
templates, logging utilities, and test data, ensuring consistency across
all usages.

**Type alias migration to `any`:**

* Replaced all instances of `interface{}` with `any` in core data
structures such as `garray` and in generated model structs (e.g.,
`TableUser`, `User1`, `User2`) to modernize type usage.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[3]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[4]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[5]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[6]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
* Updated function signatures, method parameters, and return types from
`interface{}` to `any` in various parts of the codebase, including code
generation, service logic, and logging utilities (e.g., `mlog`).
[[1]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[2]](diffhunk://#diff-2b1953fb78cf3593d8c2c7d911e95b65fd0b847c30ed0b4d167d16fe6d781235L54-R74)
[[3]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[4]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)
[[5]](diffhunk://#diff-c5d51d56f487779a2b6207c7ad26c7a20bbadcc846ce094fe60ab4cabff58c51L107-R107)
[[6]](diffhunk://#diff-f96e6a9fdb416eb1804ceaba1fe0ac637bff22c43837f8bb849c2366ce72d4a1L116-R121)
[[7]](diffhunk://#diff-f94c83a1b08ae060d9346f4a6031fc4a7b9a0b894e02d9afaa09018b6598eac0L112-R112)
[[8]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L36-R36)
[[9]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L74-R74)
[[10]](diffhunk://#diff-748b11dbe8828dd4c040ec23cae0b8fe57ecf0a2d1b7694ea39102294e633c64L96-R96)

**Generated code and templates:**

* Adjusted generated files and code generation templates to output `any`
instead of `interface{}` for relevant struct fields and function
signatures, ensuring that new code generation aligns with the updated
convention.
[[1]](diffhunk://#diff-6c19859cb32c7516ea95ddc8f8235460818eb2f24d2204308e0d9e1b19e7d90fL15-R19)
[[2]](diffhunk://#diff-a15ba2f5e830b4833c47b902515a4f9e5a4f83a3707698f3229b307ec3776b41L15-R18)
[[3]](diffhunk://#diff-52e0837e84d49221d1b810d88fdf78221f36cffcd664fb42f8aba49a79b974dcL15-R19)
[[4]](diffhunk://#diff-11c3457d1a23a4ca6ecd00d6b856289774936b6a708384cf03aff164044e7546L15-R19)
[[5]](diffhunk://#diff-2cff9cf8e6a0cc34087326d8c8149c3bbaf74c76fdbdf5a73daed13cc04249e1L15-R19)
[[6]](diffhunk://#diff-175edfeea54490b8fe4e18ffcbea5835efaf8f0b8acf623359073987cae7eb76L48-R55)
[[7]](diffhunk://#diff-e001b7a4b63603b9b14f00de78a4d570bb76c5f57d856a24643f071032e12356L66-R73)
[[8]](diffhunk://#diff-5582954e8a9983988dc8854ad82067fb2ac6269b988e07357ad8db1dfec5f1a0L39-R41)

**Container and utility updates:**

* Refactored the `garray` container implementation and related
constructors/methods to use `[]any` instead of `[]interface{}`, along
with corresponding function signatures.
[[1]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L31-R31)
[[2]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L52-R52)
[[3]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L62-R62)
[[4]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L73-R86)
[[5]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L96-R97)
[[6]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L107-R114)
[[7]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L124-R124)
[[8]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L135-R143)
[[9]](diffhunk://#diff-3a1259e160a4dfa5fe49dfe739fbdb986c0d0a2220a709882ea48d3ae1b8f911L167-R167)

These changes collectively modernize the codebase and prepare it for
future Go developments by using the idiomatic `any` type.
2025-08-28 16:53:19 +08:00

200 lines
5.0 KiB
Go

// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
// Package consul implements service Registry and Discovery using consul.
package consul
import (
"context"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/hashicorp/consul/api"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/net/gsvc"
)
const (
// DefaultTTL is the default TTL for service registration
DefaultTTL = 20 * time.Second
// DefaultHealthCheckInterval is the default interval for health check
DefaultHealthCheckInterval = 10 * time.Second
)
var (
_ gsvc.Registry = (*Registry)(nil)
)
// Registry implements gsvc.Registry interface using consul.
type Registry struct {
client *api.Client // Consul client
address string // Consul address
options map[string]string // Additional options
mu sync.RWMutex // Mutex for thread safety
}
// Option is the configuration option type for registry.
type Option func(r *Registry)
// WithAddress sets the address for consul client.
func WithAddress(address string) Option {
return func(r *Registry) {
r.mu.Lock()
r.address = address
r.mu.Unlock()
}
}
// WithToken sets the ACL token for consul client.
func WithToken(token string) Option {
return func(r *Registry) {
r.mu.Lock()
r.options["token"] = token
r.mu.Unlock()
}
}
// New creates and returns a new Registry.
func New(opts ...Option) (gsvc.Registry, error) {
r := &Registry{
address: "127.0.0.1:8500",
options: make(map[string]string),
}
// Apply options
for _, opt := range opts {
opt(r)
}
// Create consul config
config := api.DefaultConfig()
r.mu.RLock()
config.Address = r.address
if token, ok := r.options["token"]; ok {
config.Token = token
}
r.mu.RUnlock()
// Create consul client
client, err := api.NewClient(config)
if err != nil {
return nil, err
}
r.client = client
return r, nil
}
// Register registers a service to consul.
func (r *Registry) Register(ctx context.Context, service gsvc.Service) (gsvc.Service, error) {
metadata := service.GetMetadata()
if metadata == nil {
metadata = make(map[string]any)
}
// Convert metadata to string map
meta := make(map[string]string)
if len(metadata) > 0 {
metadataBytes, err := json.Marshal(metadata)
if err != nil {
return nil, gerror.Wrap(err, "failed to marshal metadata")
}
meta["metadata"] = string(metadataBytes)
}
// Add version to meta
meta["version"] = service.GetVersion()
endpoints := service.GetEndpoints()
if len(endpoints) == 0 {
return nil, gerror.New("no endpoints found in service")
}
// Create service ID
serviceID := fmt.Sprintf("%s-%s-%s:%d", service.GetName(), service.GetVersion(), endpoints[0].Host(), endpoints[0].Port())
// Create registration
reg := &api.AgentServiceRegistration{
ID: serviceID,
Name: service.GetName(),
Tags: []string{service.GetVersion()},
Meta: meta,
Address: endpoints[0].Host(),
Port: endpoints[0].Port(),
}
// Add health check
checkID := fmt.Sprintf("service:%s", serviceID)
reg.Check = &api.AgentServiceCheck{
CheckID: checkID,
TTL: DefaultTTL.String(),
DeregisterCriticalServiceAfter: "1m",
}
// Register service
if err := r.client.Agent().ServiceRegister(reg); err != nil {
return nil, gerror.Wrap(err, "failed to register service")
}
// Start TTL health check
if err := r.client.Agent().PassTTL(checkID, ""); err != nil {
// Try to deregister service if health check fails
_ = r.client.Agent().ServiceDeregister(serviceID)
return nil, gerror.Wrap(err, "failed to pass TTL health check")
}
// Start TTL health check goroutine
go r.ttlHealthCheck(serviceID)
return service, nil
}
// Deregister deregisters a service from consul.
func (r *Registry) Deregister(ctx context.Context, service gsvc.Service) error {
endpoints := service.GetEndpoints()
if len(endpoints) == 0 {
return gerror.New("no endpoints found in service")
}
// Create service ID
serviceID := fmt.Sprintf("%s-%s-%s:%d", service.GetName(), service.GetVersion(), endpoints[0].Host(), endpoints[0].Port())
return r.client.Agent().ServiceDeregister(serviceID)
}
// ttlHealthCheck maintains the TTL health check for a service
func (r *Registry) ttlHealthCheck(serviceID string) {
ticker := time.NewTicker(DefaultHealthCheckInterval)
defer ticker.Stop()
checkID := fmt.Sprintf("service:%s", serviceID)
for range ticker.C {
if err := r.client.Agent().PassTTL(checkID, ""); err != nil {
return
}
}
}
// GetAddress returns the consul address
func (r *Registry) GetAddress() string {
r.mu.RLock()
defer r.mu.RUnlock()
return r.address
}
// Watch creates and returns a watcher for specified service.
func (r *Registry) Watch(ctx context.Context, key string) (gsvc.Watcher, error) {
watcher, err := newWatcher(r, key)
if err != nil {
return nil, err
}
return watcher, nil
}