无法在Google的数据存储中存储字节数组。

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

Can't store byte array in google's datastore

问题

我正在使用Google的Datastore在我的Go应用程序中。我有一个Song结构体,其中有一个uuid.UUID字段。

type Song struct {
    ID: uuid.UUID
    Title: string
    ...
}

这个UUID是从github.com/satori/go.uuid获取的,并且被定义为

type UUID [16]byte

看起来Datastore无法处理字节数组,但在这种情况下只能处理字节切片或字符串。在json包中,我可以使用标签将其解释为字符串

type Song struct {
    ID: uuid.UUID `json:"id,string"`
    ....
}

有没有办法告诉Datastore将UUID解释为切片/字符串,或者我必须放弃"类型"安全性,只存储一个字符串或使用自定义的PropertyLoadSaver

英文:

I'm using Google's datastore in my Go app. I have a Song struct, which has a uuid.UUID field.

type Song struct {
    ID: uuid.UUID
    Title: string
    ...
}

This UUID is taken from github.com/satori/go.uuid and is defined as

type UUID [16]byte

It seems that datastore can't handle byte arrays but in this use case only byte slices or strings. In the json package I can use a tag to interpret it as a string

type Song struct {
    ID: uuid.UUID `json:"id,string"`
    ....
}

Is there a way of telling datastore to interpret the UUID as a slice/string or do I either have to give up "type"-safety and just store a string or use a custom PropertyLoadSaver?

答案1

得分: 3

根据Google的文档

有效的值类型包括:

  • 有符号整数(int、int8、int16、int32和int64)
  • 布尔值(bool)
  • 字符串(string)
  • 浮点数(float32和float64)
  • 字节切片([]byte,长度最多为1兆字节)
  • 任何底层类型为上述预声明类型之一的类型
  • ByteString
  • *Key
  • time.Time(以微秒精度存储)
  • appengine.BlobKey
  • appengine.GeoPoint
  • 所有字段都是有效值类型的结构体
  • 上述任何类型的切片

因此,你需要使用字节切片或字符串。当需要进行设置或获取时,你可以进行一些后台操作,例如(Playground示例):

type uuid [16]byte

type song struct {
    u []byte
}

func main() {
    var b [16]byte
    copy(b[:], "0123456789012345")
    
    var u uuid = uuid(b) // 表示获取到的uuid
    s := song{u: []byte(u[:])}
    
    copy(b[:], s.u)
    u = uuid(b)
    fmt.Println(u)
}

也可以通过方法来实现(Playground示例)。

另外,你还可以创建一个特定于数据存储的实体,其中包含字节切片,并且用于转换的转换器知道如何进行转换。

英文:

Per Google's Documentation:

> Valid value types are:
>

  • signed integers (int, int8, int16, int32 and int64),
  • bool,
  • string,
  • float32 and float64,
  • []byte (up to 1 megabyte in length),
  • any type whose underlying type is one of the above predeclared types,
  • ByteString,
  • *Key,
  • time.Time (stored with microsecond precision),
  • appengine.BlobKey,
  • appengine.GeoPoint,
  • structs whose fields are all valid value types,
  • slices of any of the above.

So, you will have to use a byte slice or string. You could do some behind the scenes manipulation when you need to do your setting or getting like (Playground Example):

type uuid [16]byte

type song struct {
    u []byte
}

func main() {
	var b [16]byte
	copy(b[:], "0123456789012345")
	
	var u uuid = uuid(b) //this would represent when you get the uuid
	
	s := song{u: []byte(u[:])}
	
	copy(b[:], s.u)
	u = uuid(b)
	fmt.Println(u)
}

This could also be done through methods. (Playground example)

Alternatively, you could have an entity specific to the datastore that carries the byte slice, and the transformers that go to and from that entity know how to do the conversion.

huangapple
  • 本文由 发表于 2017年4月22日 02:44:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/43549905.html
匿名

发表评论

匿名网友

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

确定