相当于存储数据的字典列表的golang

I'm learning golang. I am trying to store a little bit of data, which I will then send to file.

What would be the golang equivalent of this python block? (a list of dicts)

friends = [
  {
    "name":"James",
    "age":44,
  },
  {
    "name":"Jane",
    "age":47,
  },
]

Would it be better to use a slice of maps or a struct?

I want to be able to filter the data (for example all friends over 45) and sort the data (lets imagine I've got 12+ records). then print it to the screen.

Many use cases where you use a dict in python, you want a struct for in Go, to get static typing. In your case this looks like a slice of structs to me:

type Friend struct{
  Name string `json:"name"`
  Age  int    `json:"age"`
}

and then you can serialize/deserialize to []*Person

Puuhon’s equivalent of list is a slice, both has same semantics and use cases.

But what to put into a slice? It depends of your dicts. If they are the same fields I recommend using structs. Give it fields like above. Sometimes you have to store different keys and different string values for example. Define it as a map string to string:

map[string]string

As a last resort there’s a possibility to make dynamically typed map. But it’s not to overuse it because you lose all the benefits of static typing. Program becomes more error-prone and slower.

Given that your sample data seems to be homogeneous (friends share their properties), you can use a slice of structs, as so:

type Friend struct {
    Name string
    Age  int
}

var friends []Friend = make([]Friend, 0)

now let's say you already added friends to that slice, you can filter those with Age greater than some number:

func filterFriendsAboveAge(allFriends []Friend, minAge int) []Friend {
    results := make([]Friend, 0) 
    for _, friend := range allFriends {
        if friend.Age > minAge {
            results = append(results, friend)
        }
    }
    return results
}

Please note that by calling this function, the Friend values in the returned slice will be copies of the original. If you need to preserve identity, use pointers instead.

Here is a little sample program that does what you want:

package main

import (
    "fmt"
    "sort"
)

type friend struct {
    name string
    age  int
}

func main() {
    friends := []friend{
        {"James", 44},
        {"Jane", 47},
        {"Bob", 30},
        {"Cesar", 90},
        {"John", 45},
    }

    over45 := filterFriends(friends, func(f friend) bool {
        return f.age > 45
    })
    fmt.Println("over 45:", over45)

    // note that sort.Sort will change the contents of the slice; if you want
    // to keep the original order as well, you would first have to copy that
    // slice and sort the copy
    sort.Sort(byAge(friends))
    fmt.Println("sorted by age:", friends)
}

// filterFriends takes your slice and a predicate to filter by, then returns a
// newly allocated list of friends that made it through the filter.
func filterFriends(friends []friend, pred func(friend) bool) []friend {
    var fit []friend
    for _, f := range friends {
        if pred(f) {
            fit = append(fit, f)
        }
    }
    return fit
}

// byAge implements the sort.Interface so we can pass it to sort.Sort.
type byAge []friend

func (f byAge) Len() int           { return len(f) }
func (f byAge) Less(i, j int) bool { return f[i].age < f[j].age }
func (f byAge) Swap(i, j int)      { f[i], f[j] = f[j], f[i] }

the output of the program is:

over 45: [{Jane 47} {Cesar 90}]
sorted by age: [{Bob 30} {James 44} {John 45} {Jane 47} {Cesar 90}]