90

I'd like to create a map of string to container/list.List instances. Is this the correct way to go about it?

package main

import (
    "fmt"
    "container/list"
)

func main() {
    x := make(map[string]*list.List)

    x["key"] = list.New()
    x["key"].PushBack("value")

    fmt.Println(x["key"].Front().Value)
}
6
  • sure, but I can't help but wonder why you would need such a thing unless you were doing some really ambiguous processing Commented Oct 1, 2012 at 17:38
  • 2
    Congratulations, your code simply works. Commented Oct 1, 2012 at 18:11
  • 1
    Sure, but is it the right way of doing this? Commented Oct 1, 2012 at 19:21
  • 1
    Depends on the task, but there's nothing strange with the code. Use of a linked list is prety common, mapping a key to some value as well - and there's nothing wrong if the value is a container (or whatever does the job). Commented Oct 1, 2012 at 19:36
  • 7
    Once more: please, don't use container/List, use slices. 99% of the time you are better off learning how to use slices properly: code.google.com/p/go-wiki/wiki/SliceTricks and the remaining 1% you should probably use container/Ring. Commented Oct 3, 2012 at 8:27

3 Answers 3

199
+500

Whenever I've wanted to use a List I've found that a slice was the right choice, eg

package main

import "fmt"

func main() {
    x := make(map[string][]string)

    x["key"] = append(x["key"], "value")
    x["key"] = append(x["key"], "value1")

    fmt.Println(x["key"][0])
    fmt.Println(x["key"][1])
}
Sign up to request clarification or add additional context in comments.

2 Comments

But, the slice is kind of array, so it is not practical when the data structure needs frequent insertion/delete operations on the elements.
@yongrae, frequent inserts at the end of slice is fine, but got your point.
47

My favorite syntax for declaring a map of string to slice of string:

mapOfSlices := map[string][]string{
    "first": {},
    "second": []string{"one", "two", "three", "four", "five"},
    "third": []string{"quarter", "half"},
}

3 Comments

Can you please tell me how could I have first value as another map instead of an empty array? What would be the syntax?
You can omit the redundant []string type. So the third key for e.g. could be "third": {"quarter", "half"},
Regarding, You can omit the redundant []string type..., yes, for example, the following will give a warning: map[string][]string{"Content-Length": []string{"1"}}. It should be: map[string][]string{"Content-Length": {"1"}}.
8

there's nothing technically incorrect about what you've written, but you should define your own type around map[string]*list.List to avoid some pitfalls, like trying to call the .Front() method on a nil pointer. Or make it a map[string]list.List to avoid that situation. A list.List is just a pair of pointers and a length value; using a list.List pointer in your map just adds the extra case of a nil pointer on top of the case of an empty list. In either situation, you should define a new struct for this use case.

I would be inclined to write it like this: http://play.golang.org/p/yCTYdGVa5G

2 Comments

Thanks for code link, I realise this question is really old, just wondering why in your Add method you checked if the slice is ok? I thought you could append to a nil slice and it will resize for you, e.g. this should work even if s[key] is a nil slice: append(s[key], value)
I don't remember, it was so long ago. Not sure if that was supported back then. Maybe I liked that it lets you explicitly set the initial size of the inner slices? ¯\_(ツ)_/¯

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.