Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are lists used infrequently in Go?

Tags:

arrays

list

go

I'm new to Go, and quite excited about it. But, in all the languages I've worked with extensively: Delphi, C#, C++, Python - Lists are very important because they can be dynamically resized, as opposed to arrays.

In Golang, there is indeed a list.Liststruct, but I see very little documentation about it - whether in Go By Example or the three Go books that I have - Summerfield, Chisnal and Balbaert - they all spend a lot of time on arrays and slices and then skip to maps. In souce code examples I also find little or no use of list.List.

It also appears that, unlike Python, Range is not supported for List - big drawback IMO. Am I missing something?

Slices are certainly nice, but they still need to be based on an array with a hard coded size. That's where List comes in. Is there a way to create an array /slice in Go without a hard coded array size? Why is List ignored?

like image 202
Vector Avatar asked Jan 24 '14 06:01

Vector


People also ask

Is slice a list in Golang?

In Go, you can implement a list using a slice. These are both Go slices. Neither is a list.

What is the difference between Slice and array in Golang?

Slices in Go and Golang The basic difference between a slice and an array is that a slice is a reference to a contiguous segment of an array. Unlike an array, which is a value-type, slice is a reference type. A slice can be a complete array or a part of an array, indicated by the start and end index.

What are slices in Golang?

Slice is a variable-length sequence which stores elements of a similar type, you are not allowed to store different type of elements in the same slice. It is just like an array having an index value and length, but the size of the slice is resized they are not in fixed-size just like an array.


2 Answers

Just about always when you are thinking of a list - use a slice instead in Go. Slices are dynamically re-sized. Underlying them is a contiguous slice of memory which can change size.

They are very flexible as you'll see if you read the SliceTricks wiki page.

Here is an excerpt :-

Copy

b = make([]T, len(a)) copy(b, a) // or b = append([]T(nil), a...) 

Cut

a = append(a[:i], a[j:]...) 

Delete

a = append(a[:i], a[i+1:]...) // or a = a[:i+copy(a[i:], a[i+1:])] 

Delete without preserving order

a[i], a = a[len(a)-1], a[:len(a)-1] 

Pop

x, a = a[len(a)-1], a[:len(a)-1] 

Push

a = append(a, x) 

Update: Here is a link to a blog post all about slices from the go team itself, which does a good job of explaining the relationship between slices and arrays and slice internals.

like image 115
Nick Craig-Wood Avatar answered Oct 21 '22 11:10

Nick Craig-Wood


I asked this question a few months ago, when I first started investigating Go. Since then, every day I have been reading about Go, and coding in Go.

Because I did not receive a clear-cut answer to this question (although I had accepted one answer) I'm now going to answer it myself, based on what I have learned, since I asked it:

Is there a way to create an array /slice in Go without a hard coded array size?

Yes. Slices do not require a hard coded array to slice from:

var sl []int = make([]int, len, cap) 

This code allocates slice sl, of size len with a capacity of cap - len and cap are variables that can be assigned at runtime.

Why is list.List ignored?

It appears the main reasons list.List seem to get little attention in Go are:

  • As has been explained in @Nick Craig-Wood's answer, there is virtually nothing that can be done with lists that cannot be done with slices, often more efficiently and with a cleaner, more elegant syntax. For example the range construct:

     for i := range sl {    sl[i] = i  } 

    cannot be used with list - a C style for loop is required. And in many cases, C++ collection style syntax must be used with lists: push_back etc.

  • Perhaps more importantly, list.List is not strongly typed - it is very similar to Python's lists and dictionaries, which allow for mixing various types together in the collection. This seems to run contrary to the Go approach to things. Go is a very strongly typed language - for example, implicit type conversions never allowed in Go, even an upCast from int to int64 must be explicit. But all the methods for list.List take empty interfaces - anything goes.

    One of the reasons that I abandoned Python and moved to Go is because of this sort of weakness in Python's type system, although Python claims to be "strongly typed" (IMO it isn't). Go'slist.Listseems to be a sort of "mongrel", born of C++'s vector<T> and Python's List(), and is perhaps a bit out of place in Go itself.

It would not surprise me if at some point in the not too distant future, we find list.List deprecated in Go, although perhaps it will remain, to accommodate those rare situations where, even using good design practices, a problem can best be solved with a collection that holds various types. Or perhaps it's there to provide a "bridge" for C family developers to get comfortable with Go before they learn the nuances of slices, which are unique to Go, AFAIK. (In some respects slices seem similar to stream classes in C++ or Delphi, but not entirely.)

Although coming from a Delphi/C++/Python background, in my initial exposure to Go I found list.List to be more familiar than Go's slices, as I have become more comfortable with Go, I have gone back and changed all my lists to slices. I haven't found anything yet that slice and/or map do not allow me to do, such that I need to use list.List.

like image 23
Vector Avatar answered Oct 21 '22 11:10

Vector