英文:
Cannot pass []datastore.PropertyList to GetMulti function (datastore: src has invalid type)
问题
我已经编写了以下函数,由于传递的映射将是动态的,所以我使用了datastore.PropertyList
。单个插入使用PropertyList
可以正常工作,但在多个插入时会显示错误消息“datastore: src has invalid type”。
编辑并添加完整源代码
我错在哪里了?
package main
import (
"fmt"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
"google.golang.org/cloud"
"google.golang.org/cloud/datastore"
"io/ioutil"
)
func main() {
// 单个插入
// var map0 map[string]interface{}
// map0 = make(map[string]interface{})
// map0["Id"] = "600"
// map0["Name"] = "Prasad"
// map0["Age"] = 23
// setOneDataStore(map0)
// 多个插入
var allMaps []map[string]interface{}
allMaps = make([]map[string]interface{}, 2)
var map1 map[string]interface{}
map1 = make(map[string]interface{})
map1["Id"] = "700"
map1["Name"] = "Jay"
map1["Age"] = 23
var map2 map[string]interface{}
map2 = make(map[string]interface{})
map2["Id"] = "800"
map2["Name"] = "Peter"
map2["Age"] = 30
allMaps[0] = map1
allMaps[1] = map2
setManyDataStore(allMaps)
}
func getDataStoreClient() (client *datastore.Client, err error) {
keyFile := "JAYWORLD-30y4f7c347pq.json"
projectID := "jay-world"
jsonKey, err := ioutil.ReadFile(keyFile)
if err != nil {
fmt.Println(err.Error())
} else {
conf, err := google.JWTConfigFromJSON(
jsonKey,
datastore.ScopeDatastore,
datastore.ScopeUserEmail,
)
if err != nil {
fmt.Println(err.Error())
} else {
ctx := context.Background()
client, err = datastore.NewClient(ctx, projectID, cloud.WithTokenSource(conf.TokenSource(ctx)))
if err != nil {
fmt.Println(err.Error())
}
}
}
return
}
func setManyDataStore(Objects []map[string]interface{}) {
ctx := context.Background()
client, err := getDataStoreClient() // 在另一个函数中有连接代码
ctx = datastore.WithNamespace(ctx, "CompanyA")
if err == nil {
var keys []*datastore.Key
keys = make([]*datastore.Key, len(Objects))
var propArray []datastore.PropertyList
propArray = make([]datastore.PropertyList, len(Objects))
for index := 0; index < len(Objects); index++ {
keys[index] = datastore.NewKey(ctx, "users", Objects[index]["Id"].(string), 0, nil)
props := datastore.PropertyList{}
for key, value := range Objects[index] {
props = append(props, datastore.Property{Name: key, Value: value})
}
propArray[index] = props
}
if _, err := client.PutMulti(ctx, keys, propArray); err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Success!")
}
} else {
fmt.Println("Connection Failed")
}
}
func setOneDataStore(Object map[string]interface{}) {
ctx := context.Background()
client, err := getDataStoreClient() // 在另一个函数中有连接代码
ctx = datastore.WithNamespace(ctx, "CompanyA")
key := datastore.NewKey(ctx, "users", Object["Id"].(string), 0, nil)
props := datastore.PropertyList{}
for key, value := range Object {
props = append(props, datastore.Property{Name: key, Value: value})
}
_, err = client.Put(ctx, key, &props)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Success!")
}
}
英文:
I have wrote the following function, since passing map going to be dynamic I'm using datastore.PropertyList
. Single insert works with PropertyList
, but in Multiple
insert an error is displayed as "datastore: src has invalid type"
Edited and added the full source
Where I have gone wrong?
package main
import (
"fmt"
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
"google.golang.org/cloud"
"google.golang.org/cloud/datastore"
"io/ioutil"
)
func main() {
//Single Insert
// var map0 map[string]interface{}
// map0 = make(map[string]interface{})
// map0["Id"] = "600"
// map0["Name"] = "Prasad"
// map0["Age"] = 23
// setOneDataStore(map0)
//Multiple Insert
var allMaps []map[string]interface{}
allMaps = make([]map[string]interface{}, 2)
var map1 map[string]interface{}
map1 = make(map[string]interface{})
map1["Id"] = "700"
map1["Name"] = "Jay"
map1["Age"] = 23
var map2 map[string]interface{}
map2 = make(map[string]interface{})
map2["Id"] = "800"
map2["Name"] = "Peter"
map2["Age"] = 30
allMaps[0] = map1
allMaps[1] = map2
setManyDataStore(allMaps)
}
func getDataStoreClient() (client *datastore.Client, err error) {
keyFile := "JAYWORLD-30y4f7c347pq.json"
projectID := "jay-world"
jsonKey, err := ioutil.ReadFile(keyFile)
if err != nil {
fmt.Println(err.Error())
} else {
conf, err := google.JWTConfigFromJSON(
jsonKey,
datastore.ScopeDatastore,
datastore.ScopeUserEmail,
)
if err != nil {
fmt.Println(err.Error())
} else {
ctx := context.Background()
client, err = datastore.NewClient(ctx, projectID, cloud.WithTokenSource(conf.TokenSource(ctx)))
if err != nil {
fmt.Println(err.Error())
}
}
}
return
}
func setManyDataStore(Objects []map[string]interface{}) {
ctx := context.Background()
client, err := getDataStoreClient() //have connection code in another function
ctx = datastore.WithNamespace(ctx, "CompanyA")
if err == nil {
var keys []*datastore.Key
keys = make([]*datastore.Key, len(Objects))
var propArray []datastore.PropertyList
propArray = make([]datastore.PropertyList, len(Objects))
for index := 0; index < len(Objects); index++ {
keys[index] = datastore.NewKey(ctx, "users", Objects[index]["Id"].(string), 0, nil)
props := datastore.PropertyList{}
for key, value := range Objects[index] {
props = append(props, datastore.Property{Name: key, Value: value})
}
propArray[index] = props
}
if _, err := client.PutMulti(ctx, keys, propArray); err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Success!")
}
} else {
fmt.Println("Connection Failed")
}
}
func setOneDataStore(Object map[string]interface{}) {
ctx := context.Background()
client, err := getDataStoreClient() //have connection code in another function
ctx = datastore.WithNamespace(ctx, "CompanyA")
key := datastore.NewKey(ctx, "users", Object["Id"].(string), 0, nil)
props := datastore.PropertyList{}
for key, value := range Object {
props = append(props, datastore.Property{Name: key, Value: value})
}
_, err = client.Put(ctx, key, &props)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Success!")
}
}
答案1
得分: 3
由于错误提示中指出:“datastore: src has invalid type”,你传递给src
参数的值(&propArray
)具有无效的类型。
你不能将类型为*[]datastore.PropertyList
的值作为Client.PutMulti()
方法的src
参数传递。根据文档的描述:
src
必须满足与GetMulti
方法的dst
参数相同的条件。
而Client.GetMulti()
方法中dst
的条件如下:
dst
必须是[]S
、[]*S
、[]I
或[]P
类型,其中S
是某个结构体类型,I
是某个接口类型,P
是某个非接口非指针类型,且P
或*P
实现了PropertyLoadSaver
接口。如果是[]I
类型,每个元素都必须是Get
方法的有效dst
,即它必须是结构体指针或实现了PropertyLoadSaver
接口。
因此,你不能传递一个切片的指针,但你可以传递一个切片(去掉地址&
操作符):
if _, err := client.PutMulti(ctx, keys, propArray); err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Success!")
}
**注意:**看起来你正在创建具有特定id的键(即index
)。但是,如果键名和id都是零值,那将被视为不完整的键。由于你的index
从0
开始,你可能希望使用不同的id。
英文:
As the error indicates: "datastore: src has invalid type"
the value you pass as src
(&propArray
) has invalid type.
You can't pass a value of type *[]datastore.PropertyList
as the src
parameter of Client.PutMulti()
. Quoting from the doc:
> src
must satisfy the same conditions as the dst
argument to GetMulti
.
And the conditions of dst
at Client.GetMulti()
:
> dst
must be a []S
, []*S
, []I
or []P
, for some struct type S
, some interface type I
, or some non-interface non-pointer type P
such that P
or *P
implements PropertyLoadSaver
. If an []I
, each element must be a valid dst
for Get
: it must be a struct pointer or implement PropertyLoadSaver
.
So you can't pass a pointer to slice, but you can and you should pass a slice (drop the address &
operator):
if _, err := client.PutMulti(ctx, keys, propArray); err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Success!")
}
Note: Seemingly you are creating keys with specific ids (which is the index
). But if both the key name and id is the zero value, that is considered to be an incomplete key. Your first key will be an incomplete key as your index
starts with 0
. You might want to use different ids than the index.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论