无法将 []datastore.PropertyList 传递给 GetMulti 函数(datastore: src 的类型无效)

huangapple go评论82阅读模式
英文:

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 (
&quot;fmt&quot;
&quot;golang.org/x/net/context&quot;
&quot;golang.org/x/oauth2/google&quot;
&quot;google.golang.org/cloud&quot;
&quot;google.golang.org/cloud/datastore&quot;
&quot;io/ioutil&quot;
)
func main() {
//Single Insert
// var map0 map[string]interface{}
// map0 = make(map[string]interface{})
// map0[&quot;Id&quot;] = &quot;600&quot;
// map0[&quot;Name&quot;] = &quot;Prasad&quot;
// map0[&quot;Age&quot;] = 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[&quot;Id&quot;] = &quot;700&quot;
map1[&quot;Name&quot;] = &quot;Jay&quot;
map1[&quot;Age&quot;] = 23
var map2 map[string]interface{}
map2 = make(map[string]interface{})
map2[&quot;Id&quot;] = &quot;800&quot;
map2[&quot;Name&quot;] = &quot;Peter&quot;
map2[&quot;Age&quot;] = 30
allMaps[0] = map1
allMaps[1] = map2
setManyDataStore(allMaps)
}
func getDataStoreClient() (client *datastore.Client, err error) {
keyFile := &quot;JAYWORLD-30y4f7c347pq.json&quot;
projectID := &quot;jay-world&quot;
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, &quot;CompanyA&quot;)
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 &lt; len(Objects); index++ {
keys[index] = datastore.NewKey(ctx, &quot;users&quot;, Objects[index][&quot;Id&quot;].(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(&quot;Success!&quot;)
}
} else {
fmt.Println(&quot;Connection Failed&quot;)
}
}
func setOneDataStore(Object map[string]interface{}) {
ctx := context.Background()
client, err := getDataStoreClient() //have connection code in another function
ctx = datastore.WithNamespace(ctx, &quot;CompanyA&quot;)
key := datastore.NewKey(ctx, &quot;users&quot;, Object[&quot;Id&quot;].(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, &amp;props)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println(&quot;Success!&quot;)
}
}

答案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都是零值,那将被视为不完整的键。由于你的index0开始,你可能希望使用不同的id。

英文:

As the error indicates: &quot;datastore: src has invalid type&quot; the value you pass as src (&amp;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 &amp; operator):

if _, err := client.PutMulti(ctx, keys, propArray); err != nil {
fmt.Println(err.Error())
} else {
fmt.Println(&quot;Success!&quot;)
}

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.

huangapple
  • 本文由 发表于 2015年12月2日 15:54:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/34037461.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定