I have a map which has as value an array of maps.
Example:
thisMap["coins"][0] = aMap["random":"something"]
thisMap["notes"][1] = aMap["not-random":"something else"]
thisMap["coins"][2] = aMap["not-random":"something else"]
I can't figure it out how to do this as go seems to allow setting data only at one level when you deal with maps [name][value] = value.
So far I have this code which fails
package main
func main() {
something := []string{"coins", "notes", "gold?", "coins", "notes"}
thisMap := make(map[string][]map[string]int)
for k, v := range something {
aMap := map[string]string{
"random": "something",
}
thisMap[v] = [k]aMap
}
}
Edit: The slice values ("coins", "notes" etc ) can repeat so this is the reason why I need use an index [] .
Working example (click to play):
something := []string{"coins", "notes", "gold?"}
thisMap := make(map[string][]map[string]int)
for _, v := range something {
aMap := map[string]int{
"random": 12,
}
thisMap[v] = append(thisMap[v], aMap)
}
When iterating over the newly created thisMap, you need to make room for the new value aMap. The builtin function append does that for you when using slices. It makes room and appends the value to the slice.
If you're using more complex data types that can't be initialized as easily as slices, you first have to check if the key is already in the map and, if it is not, initialize your data type. Checking for map elements is documented here. Example with maps (click to play):
thisMap := make(map[string]map[string]int)
for _, v := range something {
if _, ok := thisMap[v]; !ok {
thisMap[v] = make(map[string]int)
}
thisMap[v]["random"] = 12
}
Related
I would like to read results from a simple SQL table like the following
customer
key
A
12345
B
6789
Now, I'd like to structure a map[string]string which has key value pairs equal to the row values like such:
map[A:12345, B:6789]
However, I am having trouble just taking the values out of the query result and dynamically creating the key-val pairs. I'll provide a rough outline of the code (the SQL connection stuff is not an issue, I have that figured out)
import "database/sql"
func main() {
// Some code to connect to MSSQL...
db, _ := sql.Open("mssql", connString)
stmt := "SELECT customer, key from tbl"
rows, _ := db.Query(stmt)
defer rows.Close()
data := make(map[string]string)
for rows.Next() {
// Need help here grabbing each row pair and adding them to my map...
}
}
I'm open to trying to do this with an Empty struct as well, where the fields become the first column of my result set (dynamic) and the value becomes the 2nd column of my result set.
You could temporarily store the values in two variables and then store them in the map:
func main() {
stmt := "SELECT customer, key from tbl"
rows, _ := db.Query(stmt)
defer rows.Close()
data := make(map[string]string)
var (
consumer string
key string
)
for rows.Next() {
if err := rows.Scan(&consumer, &key); err != nil {
// Handle err
}
data[consumer] = key
}
for k, v := range data {
fmt.Println(k, v)
}
// "A" "12345"
// "B" "6789"
}
Note that the consumer and key variables are allocated outside of the loop so we can re-use them. Even if the values are empty strings, the variables will be overwritten on each iteration.
[
{"id_A": 1, "name_A": "Value_A"},
{"id_B": 2, "name_B": "Value_B"}
]
"id_" and "name_" can change and I need to recover both the keys names to create a struct.
how can i do ?
https://play.golang.org/p/OXqpudiWWcH
if you have the key which is not fix, the only way you can use is interface{}
you need to unmarshal json to []interface{} and using type assertion to map[string]interface{}
var body []interface{}
_ = json.Unmarshal([]byte(json2), &body)
fmt.Printf("Unmarshaled: %v\n", body)
// range through array interface[]
for _, opt := range body {
// assert interface{} to map[string]interface{}
if item, ok := opt.(map[string]interface{}); ok {
for v, opt := range item {
fmt.Printf("[%s] key -> %s value -> %s\n", v, opt, "fake")
}
}
}
the complete code based on your example
https://play.golang.org/p/PepxOVlB7u4
I have this query
site.com/?status[0]=1&status[1]=2&status[1]=3&name=John
I want to get all the values of status key like
1, 2, 3
I tried something like this
for _, status:= range r.URL.Query()["status"] {
fmt.Println(status)
}
but it only works if the query is without array key: site.com/?status=1&status=2&status=3&name=John
One approach is to loop over the possible values and append to a slice as you go:
r.ParseForm() // parses request body and query and stores result in r.Form
var a []string
for i := 0; ; i++ {
key := fmt.Sprintf("status[%d]", i)
values := r.Form[key] // form values are a []string
if len(values) == 0 {
// no more values
break
}
a = append(a, values[i])
i++
}
If you have control over the query string, then use this format:
site.com/?status=1&status=2&status=3&name=John
and get status values using:
r.ParseForm()
a := r.Form["status"] // a is []string{"1", "2", "3"}
A continuation from this question:
Doing a "IN Array" query on google app engine datastore with golang
Right now, I am following the suggestion from the previous question on querying with an array of keys/ids ids []int64. These IDs may or may not actually exist (they have been deleted, but the reference on other instances have not been removed).
My method of trying to obtain these instances looks like so:
var keys []*datastore.Key
for _, id := range ids {
keys = append(keys, datastore.NewKey(c, "Category", "", id, nil))
}
categories := make([]Category, len(keys))
err := datastore.GetMulti(c, keys, categories)
if err != nil {
return nil, err
}
for i := 0; i < len(categories); i++ {
categories[i].Id = keys[i].IntID()
}
However, it errors out throwing me:
datastore: no such entity
I could on the other hand grab each one individually, but is there a more efficient way to approach this?
You need to type assert the error to an appengine.MultiError. This way you can get access to the errors for an individual entity.
if me, ok := err.(appengine.MultiError); ok {
for i, e := range me {
// e != nil if entity i failed
}
} else {
// something else went wrong (timeout, etc).
}
See the docs for MultiError here
I'm trying to find an effective example in how to perform updates on appengine datastore with Go.
All the examples I've found on the web are very vague and mostly explains concepts and not the "real life".
The appengine documentation for go says:
..."Updating an existing entity is a matter of performing another Put() using the same key."
My problem here is being in how to retrieve the key. So I have the code below to store and retrieve data:
func subscribe(w http.ResponseWriter, r *http.Request) {
user := User {
Name: r.FormValue("username"),
Email: r.FormValue("useremail"),
Flag: 0,
}
c := appengine.NewContext(r)
//datastore.Put(c, datastore.NewIncompleteKey(c, "User", nil), &user)
datastore.Put(c, datastore.NewKey(c, "User", "stringID", 0, nil), &user)
template.Must(template.ParseFiles("confirmation.html")).Execute(w, nil)
}
func checkusers(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
qUsers := datastore.NewQuery("User")
var users []User
qUsers.GetAll(c, &users)
template.Must(template.ParseFiles("users.html")).Execute(w, users)
}
How do I do an update on the flag property changing its value tom 1?
I'm a bit confused on this thing as I couldn't fully understand how the "key" is stored for each entity.
Any help would be very appreciated.
todo an update you first need to identify if your object is a new or an old one.
this can be simple done by adding the following method to your User struct:
type User struct {
Name string
Email string
Flag int64 `datastore:"-"`
}
func (u *User) IsNew() bool {
return u.Flag == 0
}
this tells data-store to ignore the Flag field when storing and retrieving an object
and because initial value of int64 is zero, a newly created object can be identified if Flag is zero
so creating a new object just needs to set UserName and Email:
user := User {
Name: r.FormValue("username"),
Email: r.FormValue("useremail")
}
then next step is to either use a IncompleteKey or a Key, for the put statement
could look like this:
var k *datastore.Key
if user.IsNew() {
k = datastore.NewIncompleteKey(c, "Users", nil)
} else {
k = datastore.NewKey(c, "Users", "", user.Flag, nil)
}
k, err := datastore.Put(c, k, user)
if err != nil {
return k, err
}
with an incomplete key, app-engine will generate a new key for you.
after put you can assign the new key to your object:
user.Flag = k.IntID
now if you do a query later you need to assign the Id to your query result objects,
the query will return the keys of query result in the same order so you can change your code like this:
keys, err := q.GetAll(c, &users)
if err != nil {
return
}
l := len(users)
for i := 0; i < l; i++ {
users[i].Flag = keys[i].IntID()
}
thats all, for more information, just have a look a the reference document there is explained with methods return which values.
https://developers.google.com/appengine/docs/go/datastore/reference