Golang中Datastore查询返回的数据与预期不符
Golang中Datastore查询返回的数据与预期不符 我是否应该期望迭代器能正确处理这个结构体的[]string属性。 数据库中有三个计划。
**计划1** ContinuingServiceTypes 和 InitialServiceTypes
{
"values": [
{
"stringValue": "s1"
},
{
"stringValue": "s2"
},
{
"stringValue": "s3"
}
]
}
**计划2** ContinuingServiceTypes 和 InitialServiceTypes
{
"values": [
{
"stringValue": "s2"
},
{
"stringValue": "s3"
}
]
}
**计划2** ContinuingServiceTypes 和 InitialServiceTypes
{
"values": [
{
"stringValue": "s3"
}
]
}
type Plan struct {
ContinuingDuration int `json:"continuingDuration"`
ContinuingServiceTypes []string `json:"continuingServiceTypes"`
InitialAssesment bool `json:"initialAssesment"`
InitialDuration int `json:"continuingDuration"`
InitialServiceTypes []string `json:"initialServiceTypes"`
OngoingMonitoring bool `json:"ongoingMonitoring"`
}
// goGetPlan 从数据存储返回计划实体数组用于测试
func goGetPlan(ts TherapistService) {
var thePlan Plan
query := datastore.NewQuery("Plan")
items := ts.DSClient.Run(ts.Ctx, query)
for {
_, err := items.Next(&thePlan)
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("Error fetching next Plan: %v", err)
}
log.Printf("The Plan %v %v", thePlan.ContinuingServiceTypes, thePlan.InitialServiceTypes)
}
}
日志语句的输出是: 计划1 [s1 s2 s3] [s1 s2 s3] 计划2 [s2 s3 s3] [s2 s3 s3] 计划3 [s3 s3 s3] [s3 s3 s3] 除非我在每次迭代后初始化[]string切片,这样输出才符合预期。我已经追踪源代码到了数据存储包的加载模块,但很遗憾后面就跟不上了。
这是我应该实现的代码类型,还是应该由库来处理?
感谢您可能提供的任何帮助。
更多关于Golang中Datastore查询返回的数据与预期不符的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你好
你正在使用同一个Plan实例进行读取。由于每次读取的元素数量不同,有时会留下旧的元素。将plan的声明移到for循环内部,这样每次都会获得一个新的实例。
约翰,
非常感谢
我想我的老习惯让我一直注意内存消耗(垃圾回收机制出现之前的年代)。我已经采纳了您的建议。现在我对 query.go 和 load.go 有了更深入的了解。
再次感谢,
约翰
在Google Cloud Datastore中,当使用迭代器循环处理多个实体时,如果结构体包含切片字段,确实需要在每次迭代时重新初始化切片,否则会出现数据重复的问题。
这是因为Datastore客户端在反序列化数据时,会向现有切片追加数据而不是替换它。当处理多个实体时,如果不重置切片,之前实体的数据会累积到后续实体中。
以下是正确的实现方式:
func goGetPlan(ts TherapistService) {
query := datastore.NewQuery("Plan")
items := ts.DSClient.Run(ts.Ctx, query)
for {
var thePlan Plan
_, err := items.Next(&thePlan)
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("Error fetching next Plan: %v", err)
}
log.Printf("The Plan %v %v", thePlan.ContinuingServiceTypes, thePlan.InitialServiceTypes)
}
}
关键变化是将 var thePlan Plan 声明移到循环内部,这样每次迭代都会创建一个新的Plan实例,切片字段自然会被初始化为空的 []string。
如果你需要在循环外部使用thePlan变量,可以显式重置切片:
func goGetPlan(ts TherapistService) {
var thePlan Plan
query := datastore.NewQuery("Plan")
items := ts.DSClient.Run(ts.Ctx, query)
for {
// 重置切片
thePlan.ContinuingServiceTypes = nil
thePlan.InitialServiceTypes = nil
_, err := items.Next(&thePlan)
if err == iterator.Done {
break
}
if err != nil {
log.Fatalf("Error fetching next Plan: %v", err)
}
log.Printf("The Plan %v %v", thePlan.ContinuingServiceTypes, thePlan.InitialServiceTypes)
}
}
这是Datastore客户端库的预期行为,需要在应用层处理切片的重置。

