snippetgoCritical
How to search for an element in a golang slice
Viewed 0 times
searchhowsliceforelementgolang
Problem
I have a slice of structs.
Here is the output of this:
How can I search this array to get the element where
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}]How can I search this array to get the element where
key="key1"?Solution
Starting with Go 1.21, there's the
IndexFunc returns the first index i satisfying f(s[i]), or -1 if none do.
Using that:
Try it on the Go Playground.
For older versions read on.
Before Go 1.21, it was part of an external repository:
Prior to Go 1.18 and for a faster alternative, read on:
With a simple
Note that since element type of the slice is a
It would be faster to use a
Notes:
It depends on your case whether multiple configs may exist with the same
Also if this is a frequent operation, you should consider building a
slices package in the standard lib with a generic search function named slices.IndexFunc():func IndexFunc[S ~[]E, E any](s S, f func(E) bool) intIndexFunc returns the first index i satisfying f(s[i]), or -1 if none do.
Using that:
idx := slices.IndexFunc(myconfig, func(c Config) bool { return c.Key == "key1" })Try it on the Go Playground.
For older versions read on.
Before Go 1.21, it was part of an external repository:
golang.org/x/exp/slices package which contains a generic "find" function named slices.IndexFunc():Prior to Go 1.18 and for a faster alternative, read on:
With a simple
for loop:for _, v := range myconfig {
if v.Key == "key1" {
// Found!
}
}Note that since element type of the slice is a
struct (not a pointer), this may be inefficient if the struct type is "big" as the loop will copy each visited element into the loop variable.It would be faster to use a
range loop just on the index, this avoids copying the elements:for i := range myconfig {
if myconfig[i].Key == "key1" {
// Found!
}
}Notes:
It depends on your case whether multiple configs may exist with the same
key, but if not, you should break out of the loop if a match is found (to avoid searching for others).for i := range myconfig {
if myconfig[i].Key == "key1" {
// Found!
break
}
}Also if this is a frequent operation, you should consider building a
map from it which you can simply index, e.g.// 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
}Code Snippets
func IndexFunc[S ~[]E, E any](s S, f func(E) bool) intidx := slices.IndexFunc(myconfig, func(c Config) bool { return c.Key == "key1" })for _, v := range myconfig {
if v.Key == "key1" {
// Found!
}
}for i := range myconfig {
if myconfig[i].Key == "key1" {
// Found!
}
}for i := range myconfig {
if myconfig[i].Key == "key1" {
// Found!
break
}
}Context
Stack Overflow Q#38654383, score: 313
Revisions (0)
No revisions yet.