Comment rechercher un élément dans une tranche de golang

J'ai une tranche de structures.

type Config struct {
Key string
Value string
}

// I form a slice of the above struct
var myconfig []Config 

// unmarshal a response body into the above slice
if err := json.Unmarshal(respbody, &myconfig); err != nil {
    panic(err)
}

fmt.Println(config)

Here is the output of this
[{key1 test} {web/key1 test2}]

Comment puis-je rechercher ce tableau pour obtenir l'élément où key="key1"?

25
demandé sur icza 2016-07-29 11:46:01

4 réponses

Avec une simple boucle for:

for _, v := range myconfig {
    if v.Key == "key1" {
        // Found!
    }
}

Notez que puisque le type d'élément de la tranche est un struct (pas un pointeur), cela peut être inefficace si le type de structure est "grand" car la boucle copiera chaque élément visité dans la variable de boucle.

, Il serait plus rapide d'utiliser un range boucle juste sur l'index, cela évite de copier les éléments:

for i := range myconfig {
    if myconfig[i].Key == "key1" {
        // Found!
    }
}

Notes:

Cela dépend de votre cas si plusieurs configs peuvent exister avec le même key, mais sinon, vous devrait break hors de la boucle si une correspondance est trouvée (pour éviter de chercher d'autres).

for i := range myconfig {
    if myconfig[i].Key == "key1" {
        // Found!
        break
    }
}

Aussi, si c'est une opération fréquente, vous devriez envisager de construire un map à partir de celui-ci que vous pouvez simplement indexer, par exemple

// Build a config map:
confMap := map[string]string{}
for _, v := range myconfig {
    confMap[v.Key] = v.Value
}

// And then to find values by key:
if v, ok := confMap["key1"]; ok {
    // Found
}
43
répondu icza 2016-07-29 08:58:34

Vous pouvez enregistrer la structure dans une carte en faisant correspondre les composants struct Key et Value à leurs parties fictives de clé et de valeur sur la carte:

mapConfig := map[string]string{}
for _, v := range myconfig {
   mapConfig[v.Key] = v.Value
}

Ensuite, en utilisant l'idiome golang comma ok, Vous pouvez tester la présence de clé:

if v, ok := mapConfig["key1"]; ok {
    fmt.Printf("%s exists", v)
}   
3
répondu Simo Endre 2017-09-22 14:30:42

Vous pouvez utiliser sort.Slice() plus sort.Search()

type Person struct {
    Name string
}

func main() {
    crowd := []Person{{"Zoey"}, {"Anna"}, {"Benni"}, {"Chris"}}

    sort.Slice(crowd, func(i, j int) bool {
        return crowd[i].Name <= crowd[j].Name
    })

    needle := "Benni"
    idx := sort.Search(len(crowd), func(i int) bool {
        return string(crowd[i].Name) >= needle
    })

    if crowd[idx].Name == needle {
        fmt.Println("Found:", idx, crowd[idx])
    } else {
        fmt.Println("Found noting: ", idx)
    }
}

Voir: https://play.golang.org/p/47OPrjKb0g_c

3
répondu Tarion 2018-03-29 15:38:43

Il n'y a pas de fonction de bibliothèque pour cela. Vous avez le code par votre propre.

for _, value := range myconfig {
    if value .Key == "key1" {
        // logic
    }
}

Code de travail: https://play.golang.org/p/IJIhYWROP_

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    type Config struct {
        Key   string
        Value string
    }

    var respbody = []byte(`[
        {"Key":"Key1", "Value":"Value1"},
        {"Key":"Key2", "Value":"Value2"}
    ]`)

    var myconfig []Config

    err := json.Unmarshal(respbody, &myconfig)
    if err != nil {
        fmt.Println("error:", err)
    }

    fmt.Printf("%+v\n", myconfig)

    for _, v := range myconfig {
        if v.Key == "Key1" {
            fmt.Println("Value: ", v.Value)
        }
    }

}
1
répondu Pravin Mishra 2016-07-29 09:26:01