Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

从1.7.0开始,查询结果为空返回的是nil了? #437

Closed
Yusoo opened this issue Feb 11, 2025 · 8 comments
Closed

从1.7.0开始,查询结果为空返回的是nil了? #437

Yusoo opened this issue Feb 11, 2025 · 8 comments

Comments

@Yusoo
Copy link

Yusoo commented Feb 11, 2025

有类似这样的结构

type DataList struct {
	List  []SqlData          `json:"list"`
	Count int            `json:"count"`
}

Expected Result

在1.6.7及之前的版本可用正常返回给前端空数组[]
{"list":[],"count":0}

Actual Result

在1.7.0及之后的版本返回的是null
{"list":null,"count":0}

导致前端大面积报错

@eatmoreapple
Copy link
Collaborator

查不到数据一直都是零值呢
看看你的代码呢 哥哥🥺

@Yusoo
Copy link
Author

Yusoo commented Feb 11, 2025

代码大致是这样

func GetData(ctx context.Context, param any) ([]entity.RealDataDTO, error) {
	rows, err := juice.NewGenericManager[[]entity.RealDataDTO](database.Engine).Object("data.getReal").QueryContext(ctx, param)
	if err != nil {
		return nil, err
	}
	return rows, nil
}

// 查询
	rows, err := service.GetData(c.Request().Context(), param)
	if err != nil {
		return err
	}
	// 组装列表分页结构
	res := entity.DataList{
		List:  rows,
		Count: len(rows),
	}
	return c.JSON(http.StatusOK, ReSuccess(res))

代码是没任何变化的,看到报错后退回到1.6.7就正常了~~

@Yusoo
Copy link
Author

Yusoo commented Feb 11, 2025

打印 fmt.Printf("%#v", rows)

1.6.7是[]entity.RealDataDTO{}
1.7.0是[]entity.RealDataDTO(nil)

应该是没有返回初始化后的空切片

@eatmoreapple
Copy link
Collaborator

是的,1.6.7 会在处理反射的时候会先去 make 一次,
1.7.0 以后没有这个操作了,减少了1 次反射 make 的开销。

1.6.7

values, err := m.mapRows(rows, isPointer, isElementImplementsScanner)
if err != nil {
	return err
}
target := rv.Elem()
// create slice with proper capacity and set the values
result := reflect.MakeSlice(target.Type(), 0, len(values))
target.Set(reflect.Append(result, values...))
return nil

1.7.0

values, err := m.mapRows(rows, isPointer, isElementImplementsScanner)
if err != nil {
	return err
}
target := rv.Elem()

// Since we've already verified the type compatibility above,
// we can safely grow the slice without additional type checks.
target.Grow(len(values))

target.Set(reflect.Append(target, values...))
return nil

@Yusoo
Copy link
Author

Yusoo commented Feb 11, 2025

那是否会修复这个问题,保持和旧版本的兼容?
GORM 和 sqlx 之类的好像也是返回初始化过的

@eatmoreapple
Copy link
Collaborator

这不是 bug,而是一个意外的特性。为了保持兼容性,新版本将默认保持返回空切片的行为,但如果你希望返回 nil 切片,可以通过设置环境变量 JUICE_RESULTMAP_PRESERVE_NIL_SLICE=true 来实现。

新版本将在 go1.24 发布之后发布。
谢谢支持🌹。

@Yusoo
Copy link
Author

Yusoo commented Feb 11, 2025

好的,辛苦了。

@eatmoreapple
Copy link
Collaborator

已经发布了

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

No branches or pull requests

2 participants