简体   繁体   中英

How to declare a Slice of Slice of structs without a set len nor capacity in Golang

I'm trying to fill grantJointResponse with slices of my struct granJoin , the data it's coming from a query and the slices can have diferent sizes. This will be easy in languagues like Python or JS, but I have tried a couple of combinations in Golang and can't make it work. I pressume has something to do with the declarations of the Slices, I have tried with grantJointResponse[contadorOwners] = make(granJoin, 0) , with grantJointResponse := [][]granJoin{} , with grantJointResponse[contadorOwners] = granJoin{} and I can' figure it out, most likely it's something easy and I'm not seeing it (I'm kind of new with Golang). This current version get an index out of range in grantJointResponse[contadorOwners] = []granJoin{auxJoin} . So if anyone knows how to do this it will be appreciated :)

import (
    "fmt"
    .
    .
    .
    "log"
    _ "github.com/lib/pq" 
    "database/sql"
)

type granJoin struct{
    property_id sql.NullInt64
    owner_id sql.NullInt64
}

rows, err := dbLeasity.Query(contractsQuery)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()
current_owner_id := int64(-1)
contadorOwners := -1
cntProp := 0
var grantJointResponse [][]granJoin
for rows.Next() {
    var auxJoin granJoin
    if err := rows.Scan(&auxJoin.owner_id, &auxJoin.property_id); err != nil {
        log.Fatal(err)
    }
    if (auxJoin.owner_id.Valid){
        if (current_owner_id == -1){
            grantJointResponse = [][]granJoin{{auxJoin}}
        }
        if (auxJoin.owner_id.Int64 != current_owner_id){
            cntProp = 0
            contadorOwners++
            current_owner_id = auxJoin.owner_id.Int64 
            if (current_owner_id != -1){
                grantJointResponse[contadorOwners] = []granJoin{auxJoin}
            }
        }
        if (cntProp != 0){
            grantJointResponse[contadorOwners] = append(grantJointResponse[contadorOwners], auxJoin)
        }
        cntProp++
    }
}

I hope to create something like this :

// Data that will be in the rows
granJoin1 = { {true, 1}, {true, 10} }
granJoin2 = { {true, 2}, {true, 11} }
granJoin3 = { {true, 2}, {true, 12} }
granJoin4 = { {true, 2}, {true, 13} }
granJoin5 = { {true, 3}, {true, 14} }
granJoin6 = { {true, 3}, {true, 15} }

//The way I need to be on the Slice of Slices 
grantJointResponse := {
  {granJoin1},
  {granJoin2, granJoin3, granJoin4},
  {granJoin5, granJoin6}
}

Start with a nil (inner) slice and a nil slice of slices. As you get new records append to the inner slice. When the owner ID changes append the inner slice to the the end of the slice of slices and set it to nil to start building another inner slice.

Note that you don't need to keep counts cntProp and contadorOwners since you just append the slice. Also, if you start with a nil slice you can just append and the underlying array will be allocated for you. Here is some code that is close to something that may work for you but I have not tested it:

rows, err := dbLeasity.Query(contractsQuery)
if err != nil {
    log.Fatal(err)
}
defer rows.Close()
current_owner_id := int64(-1)
var grantJointResponse [][]granJoin
var oneSlice []granJoin
for rows.Next() {
    var auxJoin granJoin
    if err := rows.Scan(&auxJoin.owner_id, &auxJoin.property_id); err != nil {
        log.Fatal(err)
    }
    if (auxJoin.owner_id.Valid){
        if (auxJoin.owner_id.Int64 != current_owner_id){
            if oneSlice != nil {
                grantJointResponse = append(grantJointResponse, oneSlice)
                oneSlice = nil
            }
            current_owner_id = auxJoin.owner_id.Int64
        }
        oneSlice = append(oneSlice, auxJoin)
    }
}
if oneSlice != nil {
    grantJointResponse = append(grantJointResponse, oneSlice)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM