How to get value of array key from query in golang - arrays

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"}

Related

Reading Database Rows into map[string]string

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.

Retrieve unknow key names and values from a JSON array list

[
{"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

Append for array of maps raplaces all previous array items on the latest one

The question may sound very stupid but I really don't understand what's wrong.
I want to create an array of maps like this:
values := make([]map[string]string, 0)
Then I create some map:
row := make(map[string]string)
row["item1"] = "value1"
row["item2"] = "value2"
Then append it to the array:
values = append(values, row)
Printing values now gives:
[map[item1:value1 item2:value2]]
Do the same using some other values:
row["item1"] = "value3"
row["item2"] = "value4"
values = append(values, row)
Now printing values gives:
[map[item1:value3 item2:value4] map[item1:value3 item2:value4]]
So the first array item = the second one.
What can cause this?
Full code:
package main
import "fmt"
func main() {
values := make([]map[string]string, 0)
row := make(map[string]string)
row["item1"] = "value1"
row["item2"] = "value2"
values = append(values, row)
fmt.Println(values)
row["item1"] = "value3"
row["item2"] = "value4"
values = append(values, row)
fmt.Println(values)
}
maps variables are pointers to a map so assume that your row map is in 0x50 memory address, then your values array would be some like this
values := {{0x50}, {0x50}}
so both will change by changing row.
a simple way to do that is to repeat making row again after first println or change the name of second map
Got in a minute after posting the question...
Looks like append doesn't copy map, just inserts the same.. So recreating the map each time I need to append it helps:
package main
import "fmt"
func main() {
values := make([]map[string]string, 0)
row := make(map[string]string)
row["item1"] = "value1"
row["item2"] = "value2"
values = append(values, row)
fmt.Println(values)
row2 := make(map[string]string)
row2["item1"] = "value3"
row2["item2"] = "value4"
values = append(values, row2)
fmt.Println(values)
}

How to dynamically set index of an array on run time in golang?

I have searched a lot about it but couldn't find the proper solution. what I am trying to do is to create the following as final output using arrays and slices in golang.
[
11 => [1,2,3],
12 => [4,5],
]
what I have implemented is:
type Industries struct {
IndustryId int `json:"industry_id"`
FormIds []int `json:"form_ids"`
}
var IndustrySettings IndustrySettings
_ := json.NewDecoder(c.Request.Body).Decode(&IndustrySettings)
var industryArr []int
for _, val := range IndustrySettings.IndustrySettings {
industryArr = append(industryArr, val.IndustryId)
}
In this IndustrySettings contains following json
{
"industry_settings": [{
"industry_id": 11,
"form_ids": [1, 2, 3]
},
{
"industry_id": 12,
"form_ids": [4, 5]
}
]
}
I want to loop through this json and convert into the array like industry_id as key and form_ids as values.
Can anyone please tell how to accomplish this?
Thanks!
Edit
I mean I need output like
[
11 => [1,2,3],
12 => [4,5],
]
where 11 and 12 are the industry_id as given in the json to be used as key of the array and [1,2,3], [4,5] are the form ids to be set as values in the array.
I think what you might want to do is define a struct that describes the JSON model you are trying to decode, unmarshal the JSON into a slice of that struct, and then loop through each decoded value, placing it in a map.
An example of this is here:
https://play.golang.org/p/Dz8XBnoVos
A more efficient way may be to write a customized JSON decode function and decode it into a map with key as your industry_id. But if you must use an array/slice it can be something on these lines (the first argument to the add function index can be your industry_id - change mystruct definition to whatever you need):
package main
import (
"fmt"
)
type mystruct []int
var ns []mystruct
func main() {
ns = make([]mystruct, 1, 1)
add(1, []int{2222, 24, 34})
add(7, []int{5})
add(13, []int{4,6,75})
add(14, []int{8})
add(16, []int{1, 4, 44, 67, 77})
fmt.Println("Hello, playground", ns)
}
func add(index int, ms mystruct) {
nscap := cap(ns)
nslen := len(ns)
//fmt.Println(nscap, nslen, index, ms)
if index >= nscap {
//Compute the new nslen & nscap you need
//This is just for a sample - doubling it
newnscap := index * 2
newnslen := newnscap - 1
nstemp := make([]mystruct, newnslen, newnscap)
copy(nstemp, ns)
ns = nstemp
fmt.Println("New length and capacity:", cap(ns), len(ns))
nscap = cap(ns)
nslen = len(ns)
}
//Capacity and length may have changed above, check
if index < nscap && index >= nslen {
fmt.Println("Extending slice length", nslen, "to capacity", nscap)
ns = ns[:nscap]
}
ns[index] = ms
}
On playground: https://play.golang.org/p/fgcaM1Okbl

How can I write an array of maps [golang]

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
}

Resources