2016-07-29 30 views
14

Mam plaster struktur.Jak wyszukać element w plasterku golang

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

Jak mogę przeszukać tę tablicę, aby uzyskać element, w którym key="key1"?

+0

Jak config struct wygląda prosty mapie chcę podkreślić, że można dekodować żadnych danych JSON do 'map [łańcuch] interfejs {}'. Jeśli jesteś zainteresowany, checkout [ten oficjalny wpis na blogu] (https://blog.golang.org/json-and-go) – tsabsch

Odpowiedz

25

Z prostym for pętli:

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

Należy pamiętać, że od typu element wycinka jest struct (nie wskaźnik), może być nieskuteczne, jeśli typ struct jest „duży” jako pętla skopiuj każdy odwiedzany element do zmiennej pętli.

Byłoby szybciej używać range pętlę tylko na indeksie, to unika się kopiowania elementów:

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

Uwagi:

To zależy od przypadku, czy wielokrotne configs może istnieć z ten sam key, ale jeśli nie, powinieneś break z pętli, jeśli znaleziono dopasowanie (aby uniknąć poszukiwania innych).

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

Także jeśli jest to częsta operacja, należy rozważyć budowę map od niej, które można po prostu indeks, na przykład

// 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 
} 
+0

Dzięki, że mogę również używać wskaźników. Czy myślisz, że użycie wskaźnika do struktury byłoby tu szybsze? Czy możemy mieć szereg wskaźników? – aaj

+0

@ love2code Tak, możesz użyć również plasterka wskaźników, lub jeśli przejdziesz przez indeksy (jak w moim drugim przykładzie), wartości nie zostaną skopiowane. Zależy od Ciebie. – icza

+0

ok Stworzyłem 'var myconfig [] * Config' i użyłem twojego 1. podejścia. Mam nadzieję, że jest to najlepsza opcja pod względem wydajności – aaj

2

można zapisać struct na mapie poprzez dopasowanie struktury Key i Value komponenty do ich fikcyjnych kluczy i wartości części na mapie:

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

Następnie używając golang przecinkami ok idiom można przetestować obecność klucza:

if v, ok := mapConfig["key1"]; ok { 
    fmt.Printf("%s exists", v) 
} 
1

Nie ma funkcji bibliotecznej do tego. Musisz kodować według własnego.

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

kod robocza: 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) 
     } 
    } 

}