mirror of
https://gitee.com/johng/gf
synced 2026-06-06 02:25:47 +08:00
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.
200 lines
5.0 KiB
Go
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
|
|
}
|