google-cloud-go
google-cloud-go copied to clipboard
datastore: datastore.put does not allow any non-empty value in the slice if the first value is empty with `omitempty` option
Client
Datastore
Environment
MacOS
Go Environment
$ go version
go version go1.19.2 darwin/arm64
$ go env
GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/Users/dmotylev/Library/Caches/go-build"
GOENV="/Users/dmotylev/Library/Application Support/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="/Users/dmotylev/go/pkg/mod"
GONOPROXY="github.com/redsift/*"
GONOSUMDB="github.com/redsift/*"
GOOS="darwin"
GOPATH="/Users/dmotylev/go"
GOPRIVATE="github.com/redsift/*"
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/homebrew/Cellar/go/1.19.2/libexec"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/homebrew/Cellar/go/1.19.2/libexec/pkg/tool/darwin_arm64"
GOVCS=""
GOVERSION="go1.19.2"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/dmotylev/Workshop/redsift/smart/go.mod"
GOWORK="/Users/dmotylev/Workshop/redsift/smart/go.work"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/r4/lm381q1x3mq60xmkmxz5z1l00000gn/T/go-build743168484=/tmp/go-build -gno-record-gcc-switches -fno-common"
Code
package main
import (
"context"
"fmt"
"cloud.google.com/go/datastore"
)
const (
projectId = "SOME"
)
type T struct {
Values []string `datastore:",noindex,omitempty" json:"values,omitempty"`
}
func test(client *datastore.Client, key string, want T) {
k := datastore.NameKey("test", key, nil)
fmt.Println("\nTEST", key)
_, err := client.Put(context.TODO(), k, &want)
if err != nil {
fmt.Printf("datastore.Put(%s) %s\n", key, err)
return
}
var got T
err = client.Get(context.TODO(), k, &got)
if err != nil {
fmt.Printf("datastore.Get(%s) %s\n", key, err)
return
}
fmt.Printf("want: %#v\n got: %#v\n", want, got)
}
func main() {
client, err := datastore.NewClient(context.TODO(), projectId)
if err != nil {
panic(err)
}
test(client, "empty-strings", T{Values: []string{"", "", ""}})
test(client, "non-empty-strings", T{Values: []string{"s0", "s1", "s2"}})
test(client, "1st-item-is-empty-string", T{Values: []string{"", "s1", "s2"}})
test(client, "2nd-item-is-empty-string", T{Values: []string{"s0", "", "s2"}})
// Output:
// TEST empty-strings
// want: main.T{Values:[]string{"", "", ""}}
// got: main.T{Values:[]string(nil)}
//
// TEST non-empty-strings
// want: main.T{Values:[]string{"s0", "s1", "s2"}}
// got: main.T{Values:[]string{"s0", "s1", "s2"}}
//
// TEST 1st-item-is-empty-string
// datastore.Put(1st-item-is-empty-string) datastore: unexpected property "Values" in elem 1 of slice
//
// TEST 2nd-item-is-empty-string
// want: main.T{Values:[]string{"s0", "", "s2"}}
// got: main.T{Values:[]string{"s0", "s2"}}
}
Expected behavior
The datastore put method should allow the mixing of empty and non-empty values in the array in any order.
Actual behavior
It does not allow any non-empty value if the first value is empty.
Additional context
Tested with version 1.0.0 and 1.9.0
P.S.
Not saving empty slice is expected behaviour of omitempty
, but removing empty values from the slice is not. Perhaps it is an another issue