Skip to content

fix(container): add default nil checker, rename RegisterNilChecker to SetNilChecker#1

Merged
LanceAdd merged 8 commits intoLanceAdd:fix/instances2from
gogf:fix/generic-container-nil-checker
Jan 23, 2026
Merged

fix(container): add default nil checker, rename RegisterNilChecker to SetNilChecker#1
LanceAdd merged 8 commits intoLanceAdd:fix/instances2from
gogf:fix/generic-container-nil-checker

Conversation

@gqcn
Copy link

@gqcn gqcn commented Jan 23, 2026

This pull request addresses issues with import handling in the service code generator, especially for versioned and aliased imports, and improves the generic map and array containers in the framework. It also adds comprehensive tests and updates documentation and naming for clarity and correctness.

Service Code Generation and Import Handling:

  • Updated the service code generator (genservice_calculate.go) to preserve all imports—including versioned and aliased imports—by no longer attempting to infer package names from import paths. This fixes issues where packages like "github.com/minio/minio-go/v7" were incorrectly handled due to mismatches between directory and package names. Anonymous imports are still skipped, and unused imports are left for gofmt to clean up.
  • Added a new test (Test_Issue4242) to ensure that versioned and aliased imports are correctly preserved in generated service files, preventing regressions for related issues.
  • Introduced new testdata for issue 4242, including logic and service files that use versioned and aliased imports, as well as anonymous imports, to thoroughly exercise the code generator. [1] [2] [3] [4] [5]

Generic Map (KVMap and ListKVMap) Improvements:

  • Changed the custom nil checker registration method from RegisterNilChecker to SetNilChecker for both KVMap and ListKVMap, and updated all related documentation and usage. The nil checker now uses empty.IsNil for improved nil detection. [1] [2] [3] [4] [5]
  • Improved documentation for methods that conditionally add values to the map, clarifying that nil values are not added. [1] [2] [3] [4] [5] [6]
  • Enhanced MarshalJSON documentation for all map and array types to warn against changing the receiver to a pointer, as these types may be used as value variables. [1] [2] [3] [4]
  • Added and updated tests to verify correct JSON marshaling for value-type maps and correct handling of nil values with custom nil checkers. [1] [2]

Generic Array (TArray and SortedTArray) Documentation:

  • Improved comments in TArray and SortedTArray to clarify correct usage of value receivers for MarshalJSON, and fixed a typo in NewSortedTArraySize documentation. [1] [2] [3]

These changes ensure that generated code correctly preserves complex import scenarios, improve the reliability and clarity of generic containers, and strengthen test coverage for edge cases.

LanceAdd and others added 8 commits January 22, 2026 19:04
…tching (like Spring Boot @ConfigurationProperties) (#4575)

# Loader 配置加载器

Loader 是一个通用的配置管理器,提供了类似于 Spring Boot
的`@ConfigurationProperties`的配置加载、监控、更新和管理功能。

## 功能特性

- **泛型支持**:使用 Go 泛型,类型安全的配置绑定
- **配置加载**:从配置源加载数据并绑定到结构体
- **配置监控**:自动监控配置变化并更新
- **自定义转换器**:支持自定义数据转换函数
- **回调处理**:配置变更时的回调函数
- **错误处理**:灵活的错误处理机制

## 安装

```bash
go get github.com/gogf/gf/v2
```

## 使用示例

### 1. 基本用法

#### 用法一

```go
package main

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gcfg"
	"github.com/gogf/gf/v2/os/gctx"
)

type AppConfig struct {
	Name     string       `json:"name"`
	Age      int          `json:"age"`
	Enabled  bool         `json:"enabled"`
	Features []string     `json:"features"`
	Server   ServerConfig `json:"server"`
}

type ServerConfig struct {
	Host string `json:"host"`
	Port int    `json:"port"`
}

func main() {
	ctx := gctx.New()
	// 创建配置器实例
	loader := gcfg.NewLoader[AppConfig](g.Cfg("test"), "")

	// 加载和监听配置
	loader.MustLoadAndWatch(ctx, "test-watcher")

	// 获取配置
	config := loader.Get()
	fmt.Println(config.Name)
}
```

#### 用法二

```go
package main

import (
	"fmt"
	"github.com/gogf/gf/v2/os/gcfg"
	"github.com/gogf/gf/v2/os/gctx"
)

type AppConfig struct {
	Name     string       `json:"name"`
	Age      int          `json:"age"`
	Enabled  bool         `json:"enabled"`
	Features []string     `json:"features"`
	Server   ServerConfig `json:"server"`
}

type ServerConfig struct {
	Host string `json:"host"`
	Port int    `json:"port"`
}

func main() {
	ctx := gctx.New()

	// 使用单独的适配器创建
	// 创建配置管理器
	cfg, _ := gcfg.NewAdapterFile("test.yaml")
	// 创建配置器实例
	loader := gcfg.NewLoaderWithAdapter[AppConfig](cfg, "")

	// 加载和监听配置
	loader.MustLoadAndWatch(ctx, "test-watcher")

	// 获取配置
	config := loader.Get()
	fmt.Println(config.Name)
}
```

### 2. 配置监控

```go


// 仅加载App配置
loader := gcfg.NewLoaderWithAdapter[AppConfig](cfg, "app")

// 设置配置变更回调
loader.OnChange(func (updated AppConfig) error {
// 配置变更时的处理逻辑
println("配置已更新:", updated.Name)
return nil
})

// 加载数据
err := loader.Load(ctx)
if err != nil {
panic(err)
}

// 开始监控配置变化
err := loader.Watch(context.Background(), "my-watcher")
if err != nil {
panic(err)
}

```

### 3. 自定义转换器

```go
// 设置自定义转换器
loader.SetConverter(func (data any, target *AppConfig) error {
// 自定义数据转换逻辑
return nil
})
```

### 4. 便捷方法

```go
// 一步完成加载和监控
loader.MustLoadAndWatch(context.Background(), "my-app")
```

## API 参考

### `NewLoader`

创建一个新的 Loader 实例。

```go
func NewLoader[T any](config *Config, propertyKey string, targetStruct ...*T) *Loader[T]
```

参数:

- `config`: 配置实例,用于监控变化
- `propertyKey`: 监控的属性键模式(使用 "" 或 "." 监控所有配置)
- `targetStruct`: 接收配置值的结构体指针(可选)

### `NewLoaderWithAdapter`

使用适配器创建一个新的 Loader 实例。

```go
func NewLoaderWithAdapter[T any](adapter Adapter, propertyKey string, targetStruct ...*T) *Loader[T]
```

### `Load`

从配置实例加载数据并绑定到目标结构体。

```go
func (l *Loader[T]) Load(ctx context.Context) error
```

### `MustLoad`

与 Load 类似,但出错时会 panic。

```go
func (l *Loader[T]) MustLoad(ctx context.Context)
```

### `Watch`

开始监控配置变化并自动更新目标结构体。

```go
func (l *Loader[T]) Watch(ctx context.Context, name string) error
```

### `MustWatch`

与 Watch 类似,但出错时会 panic。

```go
func (l *Loader[T]) MustWatch(ctx context.Context, name string)
```

### `MustLoadAndWatch`

便捷方法,调用 MustLoad 和 MustWatch。

```go
func (l *Loader[T]) MustLoadAndWatch(ctx context.Context, name string)
```

### `Get`

返回当前配置结构体。

```go
func (l *Loader[T]) Get() T
```

### `GetPointer() *T`

返回指向当前配置结构体的指针。

```go
func (l *Loader[T]) GetPointer() *T
```

### `OnChange`

设置配置变化时调用的回调函数。

```go
func (l *Loader[T]) OnChange(fn func (updated T) error)
```

### `SetConverter`

设置在 Load 操作期间使用的自定义转换函数。

```go
func (l *Loader[T]) SetConverter(converter func (data any, target *T) error)
```

### `SetWatchErrorHandler`

设置在 Watch 过程中 Load 操作失败时调用的错误处理函数。

```go
func (l *Loader[T]) SetWatchErrorHandler(errorFunc func(ctx context.Context, err error))
```

### `SetReuseTargetStruct`

设置是否在更新时重用相同的目标结构体或创建新结构体。

```go
func (l *Loader[T]) SetReuseTargetStruct(reuse bool)
```

### `StopWatch`

停止监控配置变化并移除关联的监控器。

```go
func (l *Loader[T]) StopWatch(ctx context.Context) (bool, error)
```

### `IsWatching`

返回 Loader 是否正在监控配置变化。

```go
func (l *Loader[T]) IsWatching() bool
```

## 高级用法

### 监控特定配置键

```go
// 只监控特定配置键
loader := gcfg.NewLoaderWithAdapter[ServerConfig](cfg, "server")
```

### 使用默认值

```go
// 创建带默认值的目标结构体
var targetConfig AppConfig
targetConfig.Name = "default-app" // 设置默认值

loader := gcfg.NewLoaderWithAdapter(cfg, "", &targetConfig)
```

## 错误处理

Loader 提供了灵活的错误处理机制:

```go
loader.SetWatchErrorHandler(func(ctx context.Context, err error) {
    // 处理加载错误
    log.Printf("配置加载失败: %v", err)
})
```

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: houseme <housemecn@gmail.com>
- Update nacos go sdk to 2.3.5;
- ctx params not use, skip it;
- adjust docs style

---------

Signed-off-by: yuluo-yx <yuluo08290126@gmail.com>
Co-authored-by: hailaz <739476267@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
)

## Summary
- Fix `gf gen service` incorrectly handling versioned imports (e.g.,
`github.com/minio/minio-go/v7` → `github.com/minio/minio-go`)
- The root cause was faulty package name inference from import paths -
Go allows package names to differ from directory names
- Solution: Keep all non-anonymous imports and let gofmt clean up unused
ones

## Changes
- Simplified `calculateImportedItems` function in
`genservice_calculate.go`
- Added test case for versioned imports and aliased imports

## Test plan
- [x] All existing genservice tests pass (`Test_Gen_Service_Default`,
`Test_Issue3328`, `Test_Issue3835`)
- [x] New test `Test_Issue4242` verifies both versioned imports and
aliased imports are preserved
- [x] Verified generated files match expected output exactly

Closes #4242

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@LanceAdd LanceAdd merged commit 9c32819 into LanceAdd:fix/instances2 Jan 23, 2026
13 checks passed
@LanceAdd LanceAdd deleted the fix/generic-container-nil-checker branch January 23, 2026 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants