Golang - How to iterate through two slices at the same time - arrays

I'm trying to write a function that takes in a struct, and within that there are two nested structs. I need to iterate through both nested structs, find the "Service" field and remove the prefixes that are separated by the '-'.
I've written a function that does what I want it to and removes the prefixes, however it consists of two for loops that loop through the two separate structs. Is their a way for me to write this function in a way that it loops through the structs in one for loop?
Here are the structs:
var myJson = `
{
"ID": "hgfd5432",
"Greeting": "Welcome!",
"ServiceNames": [
{
"Service": "sevice-name-service1",
"Version": "1.8"
},
{
"Service": "sevice-name-service2",
"Version": "1.8"
},
{
"Service": "sevice-name-service3",
"Version": "1.9"
},
{
"Service": "sevice-name-service4",
"Version": "0.6"
}
],
"Services": [
{
"Service": "sevice-name-service5",
"Version": "1.8"
}
],
"BusinessUnit": "Unit 1",
"Queue": "UK73_Advocacy_PCCT",
"Input": "Default",
}`
type Profile struct {
ProfileId string `json:"ID"`
Input string `json:"Input"`
ParentProfile string `json:"ParentProfile"`
Persona string `json:"Persona"`
BusinessUnit string `json:"BusinessUnit"`
Greeting string `json:"Greeting"`
Queue string `json:"Queue"`
ServiceNames []ServiceKey `json:"ServiceNames"`
Services []ServiceInfo `json:"Services"`
And here is the function:
func removePrefix(inputParameters *Profile) error {
for i := 0; i < len(inputParameters.ServiceNames); i++ {
a := strings.Split(inputParameters.ServiceNames[i].Service, "-")
s := a[len(a)-1]
inputParameters.ServiceNames[i].Service = s
}
for i := 0; i < len(inputParameters.Services); i++ {
a := strings.Split(inputParameters.Services[i].Service, "-")
s := a[len(a)-1]
inputParameters.Services[i].Service = s
}
return nil

One way you can do this is,
serviceNamesLength := len(inputParameters.ServiceNames)
servicesLength := len(inputParameters.Services)
maxLength := serviceNamesLength
if servicesLength > maxLength {
maxLength = servicesLength
}
for i := 0; i < maxLength; i++ {
if i < servicesLength {
// services stuff
}
if i < serviceNamesLength {
// services names stuff
}
}

here's how you can do this,by using concurrency:
func ConcurrencyLoop(inputParameters *Profile) {
done := make(chan interface{})
var wg sync.WaitGroup
wg.Add(2)
servicesNameChan := TransformServiceNames(done, inputParameters.ServiceNames, &wg)
servicesInfoChan := TransformServiceInfo(done, inputParameters.Services, &wg)
if servicesName, ok := <-servicesNameChan; ok {
inputParameters.ServiceNames = servicesName
}
if servicesInfo, ok := <-servicesInfoChan; ok {
inputParameters.Services = servicesInfo
}
close(done)
wg.Wait()
}
func TransformServiceNames(done <-chan interface{}, servicesKey []ServiceKey, wg *sync.WaitGroup) <-chan []ServiceKey {
keysChan := make(chan []ServiceKey)
go func() {
defer wg.Done()
transformedServicekeys := make([]ServiceKey, 0)
for _, serviceKey := range servicesKey {
a := strings.Split(serviceKey.Service, "-")
s := a[len(a)-1]
transformedServicekeys = append(transformedServicekeys, ServiceKey{
Service: s,
})
}
for {
select {
case <-done:
return
case keysChan <- transformedServicekeys:
}
}
}()
return keysChan
}
func TransformServiceInfo(done <-chan interface{}, servicesKey []ServiceInfo, wg *sync.WaitGroup) <-chan []ServiceInfo {
keysChan := make(chan []ServiceInfo)
go func() {
defer wg.Done()
transformedServiceinfo := make([]ServiceInfo, 0)
for _, serviceKey := range servicesKey {
a := strings.Split(serviceKey.Service, "-")
s := a[len(a)-1]
transformedServiceinfo = append(transformedServiceinfo, ServiceInfo{
Service: s,
})
}
for {
select {
case <-done:
return
case keysChan <- transformedServiceinfo:
}
}
}()
return keysChan
}

Related

Getting file content into a multidimensional string var

I'm using the fsnotify packet to wait for changes in a json file.
I have two problems with this code. The first one is regarding the info returned by ReadFile function. Looks like when I print something returned by the function is empty.
Second issue is regarding the fsnotify that is not reading the file the first time unless i do some modification on the content. I must read the file from the beggining as well.
type Information struct {
Info []Info `json:"info"`
}
type Info struct {
Type string `json:"type"`
News []New `json:"news"`
}
type New struct {
Name string `json:"name"`
Read bool `json:"read"`
}
func ReadFile(file_name string) *Information {
jsonFile, err := os.Open(file_name)
if err != nil {
fmt.Println(err)
}
fmt.Println("Successfully Opened file_name.json")
defer jsonFile.Close()
byteValue, _ := ioutil.ReadAll(jsonFile)
var infor Information
json.Unmarshal(byteValue, &infor)
return &infor
}
// main function
func main() {
// read json file using fsnotify to wait for changes
watcher, err := fsnotify.NewWatcher()
if err != nil {
panic(err)
}
err = watcher.Add(file_json)
if err != nil {
panic(err)
}
for {
select {
case ev, ok := <-watcher.Events:
log.Println("event:", ev)
if !ok {
return
}
if ev.Op&fsnotify.Write == fsnotify.Write {
data := ReadFile(file_name)
fmt.Print("INFORMATION ABOUT FILE:\n")
for _, info := range data.Info {
fmt.Printf("Info type: %s\n", info.Type) // Here is not printing the result of info.Type
for _, news := range info.News {
fmt.Printf("News Name: %s\n", news.Name) // Here is not printing even "News Name:" or News Read:"
fmt.Printf("News Read: %s\n", strconv.FormatBool(news.Read))
}
}
}
case err := <-watcher.Errors:
log.Println("error:", err)
}
}
}
This is the json file:
{
    "info": [
      {
        "type": "general",
        "news": [
          { "name": "abc",  "read": true },
          { "name": "def",  "read": true }
        ]
      },
{
"type": "confidential",
"news": [
{ "name": "xxx", "read": false },
{ "name": "yyy", "read": false }
]
},
]
}
type Information struct {
Info []Info `json:"info"`
}
type Info struct {
Type string `json:"type"`
News []New `json:"news"` // Here should be a slice define.
}
type New struct {
Name string `json:"name"`
Read bool `json:"read"`
}
func ReadFile(file_name string) *Information {
jsonFile, err := os.Open(file_name)
if err != nil {
fmt.Println(err)
}
fmt.Println("Successfully Opened file_name.json")
defer jsonFile.Close()
byteValue, _ := ioutil.ReadAll(jsonFile)
var infor Information
json.Unmarshal(byteValue, &infor)
return &infor
}
func main() {
data := ReadFile("./data.json")
for _, news := range data.Info {
for _, v := range news.News {
name := v.Name
// Add you want to do
fmt.Println(name)
}
}
}
You can not get like this:
getInfo = [general][abc, true, def, true]
[confidential][xxx, false, yyy, false]

How to remove duplicates strings or int from Slice in Go

Let's say I have a list of student cities and the size of it could be 100 or 1000, and I want to filter out all duplicates cities.
I want a generic solution that I can use to remove all duplicate strings from any slice.
I am new to Go Language, So I tried to do it by looping and checking if the element exists using another loop function.
Students' Cities List (Data):
studentsCities := []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}
Functions that I created, and it's doing the job:
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func removeDuplicates(strList []string) []string {
list := []string{}
for _, item := range strList {
fmt.Println(item)
if contains(list, item) == false {
list = append(list, item)
}
}
return list
}
My solution test
func main() {
studentsCities := []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}
uniqueStudentsCities := removeDuplicates(studentsCities)
fmt.Println(uniqueStudentsCities) // Expected output [Mumbai Delhi Ahmedabad Bangalore Kolkata Pune]
}
I believe that the above solution that I tried is not an optimum solution. Therefore, I need help from you guys to suggest the fastest way to remove duplicates from the slice?
I checked StackOverflow, this question is not being asked yet, so I didn't get any solution.
I found Burak's and Fazlan's solution helpful. Based on that, I implemented the simple functions that help to remove or filter duplicate data from slices of strings, integers, or any other types with generic approach.
Here are my three functions, first is generic, second one for strings and last one for integers of slices. You have to pass your data and return all the unique values as a result.
Generic solution: => Go v1.18
func removeDuplicate[T string | int](sliceList []T) []T {
allKeys := make(map[T]bool)
list := []T{}
for _, item := range sliceList {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}
To remove duplicate strings from slice:
func removeDuplicateStr(strSlice []string) []string {
allKeys := make(map[string]bool)
list := []string{}
for _, item := range strSlice {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}
To remove duplicate integers from slice:
func removeDuplicateInt(intSlice []int) []int {
allKeys := make(map[int]bool)
list := []int{}
for _, item := range intSlice {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}
You can update the slice type, and it will filter out all duplicates data for all types of slices.
Here is the GoPlayground link: https://go.dev/play/p/iyb97KcftMa
Adding this answer which worked for me, does require/include sorting, however.
func removeDuplicateStrings(s []string) []string {
if len(s) < 1 {
return s
}
sort.Strings(s)
prev := 1
for curr := 1; curr < len(s); curr++ {
if s[curr-1] != s[curr] {
s[prev] = s[curr]
prev++
}
}
return s[:prev]
}
For fun, I tried using generics! (Go 1.18+ only)
type SliceType interface {
~string | ~int | ~float64 // add more *comparable* types as needed
}
func removeDuplicates[T SliceType](s []T) []T {
if len(s) < 1 {
return s
}
// sort
sort.SliceStable(s, func(i, j int) bool {
return s[i] < s[j]
})
prev := 1
for curr := 1; curr < len(s); curr++ {
if s[curr-1] != s[curr] {
s[prev] = s[curr]
prev++
}
}
return s[:prev]
}
Go Playground Link with tests: https://go.dev/play/p/bw1PP1osJJQ
You can do in-place replacement guided with a map:
processed := map[string]struct{}{}
w := 0
for _, s := range cities {
if _, exists := processed[s]; !exists {
// If this city has not been seen yet, add it to the list
processed[s] = struct{}{}
cities[w] = s
w++
}
}
cities = cities[:w]
reduce memory usage:
package main
import (
"fmt"
"reflect"
)
type void struct{}
func main() {
digits := [6]string{"one", "two", "three", "four", "five", "five"}
set := make(map[string]void)
for _, element := range digits {
set[element] = void{}
}
fmt.Println(reflect.ValueOf(set).MapKeys())
}
p.s. playground
Simple to understand.
func RemoveDuplicate(array []string) []string {
m := make(map[string]string)
for _, x := range array {
m[x] = x
}
var ClearedArr []string
for x, _ := range m {
ClearedArr = append(ClearedArr, x)
}
return ClearedArr
}
If you want to don't waste memory allocating another array for copy the values, you can remove in place the value, as following:
package main
import "fmt"
var studentsCities = []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}
func contains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
func main() {
fmt.Printf("Cities before remove: %+v\n", studentsCities)
for i := 0; i < len(studentsCities); i++ {
if contains(studentsCities[i+1:], studentsCities[i]) {
studentsCities = remove(studentsCities, i)
i--
}
}
fmt.Printf("Cities after remove: %+v\n", studentsCities)
}
func remove(slice []string, s int) []string {
return append(slice[:s], slice[s+1:]...)
}
Result:
Cities before remove: [Mumbai Delhi Ahmedabad Mumbai Bangalore Delhi Kolkata Pune]
Cities after remove: [Ahmedabad Mumbai Bangalore Delhi Kolkata Pune]
It can also be done with a set-like map:
ddpStrings := []string{}
m := map[string]struct{}{}
for _, s := range strings {
if _, ok := m[scopeStr]; ok {
continue
}
ddpStrings = append(ddpStrings, s)
m[s] = struct{}{}
}
func UniqueNonEmptyElementsOf(s []string) []string {
unique := make(map[string]bool, len(s))
var us []string
for _, elem := range s {
if len(elem) != 0 {
if !unique[elem] {
us = append(us, elem)
unique[elem] = true
}
}
}
return us
}
send the duplicated splice to the above function, this will return the splice with unique elements.
func main() {
studentsCities := []string{"Mumbai", "Delhi", "Ahmedabad", "Mumbai", "Bangalore", "Delhi", "Kolkata", "Pune"}
uniqueStudentsCities := UniqueNonEmptyElementsOf(studentsCities)
fmt.Println(uniqueStudentsCities)
}
Here's a mapless index based slice's duplicate "remover"/trimmer. It use a sort method.
The n value is always 1 value lower than the total of non duplicate elements that's because this methods compare the current (consecutive/single) elements with the next (consecutive/single) elements and there is no matches after the lasts so you have to pad it to include the last.
Note that this snippet doesn't empty the duplicate elements into a nil value. However since the n+1 integer start at the duplicated item's indexes, you can loop from said integer and nil the rest of the elements.
sort.Strings(strs)
for n, i := 0, 0; ; {
if strs[n] != strs[i] {
if i-n > 1 {
strs[n+1] = strs[i]
}
n++
}
i++
if i == len(strs) {
if n != i {
strs = strs[:n+1]
}
break
}
}
fmt.Println(strs)
Based on Riyaz's solution, you can use generics since Go 1.18
func removeDuplicate[T string | int](tSlice []T) []T {
allKeys := make(map[T]bool)
list := []T{}
for _, item := range tSlice {
if _, value := allKeys[item]; !value {
allKeys[item] = true
list = append(list, item)
}
}
return list
}
Generics minimizes code duplication.
Go Playground link : https://go.dev/play/p/Y3fEtHJpP7Q
So far #snassr has given the best answer as it is the most optimized way in terms of memory (no extra memory) and runtime (nlogn). But one thing I want to emphasis here is if we want to delete any index/element of an array we should loop from end to start as it reduces complexity. If we loop from start to end then if we delete nth index then we will accidentally miss the nth element (which was n+1th before deleting nth element) as in the next iteration we will get the n+1th element.
Example Code
func Dedup(strs []string) {
sort.Strings(strs)
for i := len(strs) - 1; i > 0; i-- {
if strs[i] == strs[i-1] {
strs = append(strs[:i], strs[i+1:]...)
}
}
}
try: https://github.com/samber/lo#uniq
names := lo.Uniq[string]([]string{"Samuel", "John", "Samuel"})
// []string{"Samuel", "John"}

Recursively changing arrays to non-arrays in JSON with sjson in Golang

What I'm trying to do:
Transform all arrays of length 1 in a JSON file to non arrays.
e.g.
Input: {"path": [{"secret/foo": [{"capabilities": ["read"]}]}]}
Output: {"path": {"secret/foo": {"capabilities": "read"}}}
I can't use Structs as the JSON format will vary...
Right now I've managed to at least detect the 1 length slices:
package main
import (
"encoding/json"
"fmt"
)
func findSingletons(value interface{}) {
switch value.(type) {
case []interface{}:
if len(value.([]interface{})) == 1 {
fmt.Println("1 length array found!", value)
}
for _, v := range value.([]interface{}) {
findSingletons(v)
}
case map[string]interface{}:
for _, v := range value.(map[string]interface{}) {
findSingletons(v)
}
}
}
func removeSingletonsFromJSON(input string) {
jsonFromInput := json.RawMessage(input)
jsonMap := make(map[string]interface{})
err := json.Unmarshal([]byte(jsonFromInput), &jsonMap)
if err != nil {
panic(err)
}
findSingletons(jsonMap)
fmt.Printf("JSON value of without singletons:%s\n", jsonMap)
}
func main() {
jsonParsed := []byte(`{"path": [{"secret/foo": [{"capabilities": ["read"]}]}]}`)
removeSingletonsFromJSON(string(jsonParsed))
fmt.Println(`Should have output {"path": {"secret/foo": {"capabilities": "read"}}}`)
}
Which outputs
1 length array found! [map[secret/foo:[map[capabilities:[read]]]]]
1 length array found! [map[capabilities:[read]]]
1 length array found! [read]
JSON value of without singletons:map[path:[map[secret/foo:[map[capabilities:[read]]]]]]
Should have output {"path": {"secret/foo": {"capabilities": "read"}}}
But I'm not sure how I can change them into non-arrays...
The type switch is your friend:
switch t := v.(type) {
case []interface{}:
if len(t) == 1 {
data[k] = t[0]
And you may use recursion to remove inside elements, like so:
func removeOneElementSlice(data map[string]interface{}) {
for k, v := range data {
switch t := v.(type) {
case []interface{}:
if len(t) == 1 {
data[k] = t[0]
if v, ok := data[k].(map[string]interface{}); ok {
removeOneElementSlice(v)
}
}
}
}
}
I would do this to convert
{"path":[{"secret/foo":[{"capabilities":["read"]}]}]}
to
{"path":{"secret/foo":{"capabilities":"read"}}}:
package main
import (
"encoding/json"
"fmt"
"log"
)
func main() {
s := `{"path":[{"secret/foo":[{"capabilities":["read"]}]}]}`
fmt.Println(s)
var data map[string]interface{}
if err := json.Unmarshal([]byte(s), &data); err != nil {
panic(err)
}
removeOneElementSlice(data)
buf, err := json.Marshal(data)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(buf)) //{"a":"a","n":7}
}
func removeOneElementSlice(data map[string]interface{}) {
for k, v := range data {
switch t := v.(type) {
case []interface{}:
if len(t) == 1 {
data[k] = t[0]
if v, ok := data[k].(map[string]interface{}); ok {
removeOneElementSlice(v)
}
}
}
}
}

How to break out of nested loops in Go?

I have an outer and inner loop, each iterating over a range. I want to exit the outer loop when a condition is satisfied inside the inner loop.
I have a solution which works using two 'break's, one inside the inner loop and one inside the outerloop, just outside the inner loop (a very simplified case for demonstration):
package main
import (
"fmt"
)
func main() {
word := ""
for _, i := range("ABCDE") {
for _,j := range("ABCDE") {
word = string(i) + string(j)
fmt.Println(word)
if word == "DC" {
break
}
}
if word == "DC" {
break
}
}
// More logic here that needs to be executed
}
Go Playground
There is no problem with this solution, but it just looks patched and ugly to me. Is there a better way to do this?
I can try and have another for conditional loop outside the outer loop in the previous solution and have a label and use continue with the label. But as you can see, this approach isn't any more elegant than the solution with break.
package main
import (
"fmt"
)
func main() {
word := ""
Exit:
for word != "DC" {
for _, i := range "ABCDE" {
for _, j := range "ABCDE" {
word = string(i) + string(j)
fmt.Println(word)
if word == "DC" {
continue Exit
}
}
}
}
// More logic here that needs to be executed
}
Go Playground
I have seen similar questions here pertaining to other languages (C, C#, Python etc). But what I am really interested to see is whether there is any trick with Go constructs such as 'for select'.
Use break {label} to break out of any loop as nested as you want. Just put the label before the for loop you want to break out of. This is fairly similar to the code that does a goto {label} but I think a tad more elegant, but matter of opinion I guess.
package main
func main() {
out:
for i := 0; i < 10; i++ {
for j := 0; j < 10; j++ {
if i + j == 20 {
break out
}
}
}
}
More details: https://www.ardanlabs.com/blog/2013/11/label-breaks-in-go.html
use function
package main
import (
"fmt"
)
func getWord() string {
word := ""
for word != "DC" {
for _, i := range "ABCDE" {
for _, j := range "ABCDE" {
word = string(i) + string(j)
fmt.Println(word)
if word == "DC" {
return word
}
}
}
}
return word
}
func main(){
word := getWord()
}
Edit: thanks to #peterSO who points on some mistakes in the details and provides this playground https://play.golang.org/p/udcJptBW9pQ
How about goto?
package main
import (
"fmt"
)
func main() {
word := ""
for _, i := range "ABCDE" {
for _, j := range "ABCDE" {
word = string(i) + string(j)
fmt.Println(word)
if word == "DC" {
goto Exit
}
}
}
Exit: // More logic here that needs to be executed
}
The most straightforward seems to be something like:
func main() {
word := ""
isDone := false
for _, i := range("ABCDE") {
for _,j := range("ABCDE") {
word = string(i) + string(j)
fmt.Println(word)
isDone = word == "DC"
if isDone {
break
}
}
if isDone {
break
}
}
// other stuff
}
An Alternative using a Generator
However you could also do a generator to create the sequence of words as in:
func makegen () chan string {
c:= make(chan string)
go func () {
for _, i := range ("ABCDE") {
for _, j := range ("ABCDE") {
c <- string(i) + string(j)
}
}
close (c)
}()
return c
}
func main() {
word := ""
for word = range makegen() {
fmt.Println (word)
if word == "DC" {
break
}
}
// other code
}
An improved version of the generator function that will clean up the resource leak identified by a comment below.
func makegen () chan string {
c:= make(chan string)
go func () {
word := ""
for _, i := range ("ABCDE") {
for _, j := range ("ABCDE") {
word = string(i) + string(j)
c <- word
if word == "DC" {
close (c)
return
}
}
}
close (c)
}()
return c
}
func main() {
word := ""
for word = range makegen() {
fmt.Println (word)
}
// other code
}
Wrap your for loops in an anonymous self-invoked function, then just return whenever you want to break out
package main
func main() {
func() {
for i:= 0; i < 100; i++ {
for j:= 0; j < 100; j++ {
if (i == 5 && j == 5) {
return
}
}
}
}()
}
Just defer anything you need to do and return as normal.
package main
import (
"fmt"
)
func main() {
defer func() {
// More logic here that needs to be executed
}()
word := ""
for _, i := range "ABCDE" {
for _, j := range "ABCDE" {
word = string(i) + string(j)
fmt.Println(word)
if word == "DC" {
return
}
}
}
}

Only last row is printing

this is my go function
func logInFirst(res http.ResponseWriter, req *http.Request) {
type Resp struct {
Result []map[string]interface{} `json:"Result,omitempty"`
Result1 []map[string]interface{} `json:"Result1,omitempty"`
Result2 []map[string]interface{} `json:"Result2,omitempty"`
Status string `json:"Status"`
}
type AxleUser struct {
ShopID string `json:"ShopID"`
VehicleType string `json:"VehicleType"`
}
var Response Resp
Response.Status = "failed"
Result := make(map[string]interface{})
Result1 := make(map[string]interface{})
Result2 := make(map[string]interface{})
//db, err := sql.Open("mysql", "root:chikkIbuddI57#tcp(127.0.0.1:3306)/b2b")
db, err := sql.Open("mysql", "awsgobumpr:gobumpr123#tcp(briaxpgbmpr.cx4twoxoumct.ap-southeast-1.rds.amazonaws.com)/b2b_optimization")
if err != nil {
panic(err.Error())
}
defer db.Close()
rnd := render.New()
b, err := ioutil.ReadAll(req.Body)
defer req.Body.Close()
if err != nil {
panic(err.Error())
}
// Unmarshal the request body
var msg AxleUser
err = json.Unmarshal(b, &msg)
if err != nil {
panic(err.Error())
}
//fmt.Println(msg)
// get shop id from emp table using mobile number and password
brandrows, branderr := db.Query("SELECT DISTINCT brand,model FROM admin_vehicle_table_new WHERE type=?", msg.VehicleType)
if branderr != nil {
panic(branderr.Error())
}
brandcolumns, branderr := brandrows.Columns()
if branderr != nil {
panic(branderr.Error())
}
brandcount := len(brandcolumns)
brandValues := make([]string, brandcount)
brandScanArgs := make([]interface{}, brandcount)
for i := range brandValues {
brandScanArgs[i] = &brandValues[i]
}
for brandrows.Next() {
branderr := brandrows.Scan(brandScanArgs...)
//fmt.Println(branderr)
if branderr != nil {
panic(branderr.Error())
}
for i, v := range brandValues {
Result[brandcolumns[i]] = v
}
Response.Result = append(Response.Result, Result)
}
servicerows, serviceerr := db.Query("SELECT DISTINCT b2b_service_type FROM b2b_service_type WHERE b2b_vehicle_type=? and b2b_flag=0 and b2b_shop_id=0 UNION SELECT b2b_service_type FROM b2b_service_type WHERE b2b_vehicle_type=? and b2b_flag=0 and b2b_shop_id=?", msg.VehicleType, msg.VehicleType, msg.ShopID)
if serviceerr != nil {
panic(serviceerr.Error())
}
servicecolumns, serviceerr := servicerows.Columns()
if serviceerr != nil {
panic(serviceerr.Error())
}
servicecount := len(servicecolumns)
serviceValues := make([]string, servicecount)
serviceScanArgs := make([]interface{}, servicecount)
for i := range serviceValues {
serviceScanArgs[i] = &serviceValues[i]
}
for servicerows.Next() {
serviceerr := servicerows.Scan(serviceScanArgs...)
if serviceerr != nil {
panic(serviceerr.Error())
}
for i, v := range serviceValues {
Result1[servicecolumns[i]] = v
}
Response.Result1 = append(Response.Result1, Result1)
}
repairrows, repairerr := db.Query("SELECT DISTINCT b2b_repair_decription FROM b2b_repair_decription WHERE b2b_vehicle_type=? and b2b_shop_id=0 UNION SELECT b2b_repair_decription FROM b2b_repair_decription WHERE b2b_vehicle_type=? and b2b_shop_id=?", msg.VehicleType, msg.VehicleType, msg.ShopID)
if repairerr != nil {
panic(repairerr.Error())
}
repaircolumns, repairerr := repairrows.Columns()
if repairerr != nil {
panic(repairerr.Error())
}
repaircount := len(repaircolumns)
repairValues := make([]string, repaircount)
repairScanArgs := make([]interface{}, repaircount)
for i := range repairValues {
repairScanArgs[i] = &repairValues[i]
}
for repairrows.Next() {
repairerr := repairrows.Scan(repairScanArgs...)
if repairerr != nil {
panic(repairerr.Error())
}
for i, v := range repairValues {
Result2[repaircolumns[i]] = v
}
Response.Result2 = append(Response.Result2, Result2)
}
Response.Status = "success"
res.Header().Set("Content-Type", "application/json")
rnd.JSON(res, http.StatusOK, Response)
}
My Desrired output is a json string like this
{
"Result": [
{
"brand": "Hero Honda",
"model": "Passion Pro"
},
{
"brand": "Yamaha",
"model": "120"
},...
]
"Result1":[
{
"service_type" : "repairs",
},
{
"service_type" : "general service",
},...
]
"Result2":[
{
"b2b_repair_decription": "Tire Replacement"
},
{
"b2b_repair_decription": "Electric work"
},...
]
}
but the output which i got contains the same row instead of all the rows like
this,
{
"Result": [
{
"brand": "Yamaha",
"model": "120"
},
{
"brand": "Yamaha",
"model": "120"
},...
]
"Result1":[
{
"service_type" : "general service",
},
{
"service_type" : "general service",
},...
]
"Result2":[
{
"b2b_repair_decription": "Electric work"
},
{
"b2b_repair_decription": "Electric work"
},...
]
}
i tried appending in the loop , but it dint work. i even tried defining the Result, Result1, Result2 as array of interfaces
can someone help me with this issue?

Resources