Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Some complaints also seem like a lack of experience using the language. For example

   Initialization with make behaves differently for maps and slices:

   m := make(map[int]int, 10) // capacity = 10, length = 0
   a := make([]int,       10) // capacity = 10, length = 10 (zero initialization)
   b := make([]int,    0, 10) // capacity = 10, length = 0
   So not only is there an inconsistency, the more common operation has a longer spelling.
In my experience, the two-value (explicit capacity) form of "make" is significantly _less_ common than the single-value form. Indeed, gripping through the stdlib shows "make([]T, n) is much more common than "make([]T, n, m)".

I agree that appending to "make([]T, n)" is not an uncommon mistake. But, in general, you can avoid that problem by assigning to specific indices instead of using append.

I think the place I regularly use "make([]T, 0, n)" is when I'm collecting items from a

   s := make([]K, 0, len(m))
   for k, v := range m {
       s = append(s, k
   }


> Some complaints also seem like a lack of experience using the language.

> In my experience, the two-value (explicit capacity) form of "make" is significantly _less_ common than the single-value form. Indeed, gripping through the stdlib shows "make([]T, n) is much more common than "make([]T, n, m)".

I've written a fair bit of C++, where this pattern is very common. IME in 95%+ of the cases, what one wants is a vector with a capacity without initializing it, because it will be filled up right away.

I'd argue that make([]T, n) is more common in actual Go code precisely because it has the shorter spelling, not because it has the exact desired semantics.


Ah. But this is writing C++ in Go instead of writing Go in Go.

In C++ I'd write something like

  std::vector<T> vector;
  vector.reserve(10);
  for (auto i = 0; i < 10; i++) {
    vector.push_back(...);
  }
but in Go I'd write

  vec := make([]T, 10)
  for i := 0; i < 10; i++ {
      vec[i] = ...
  }
Just like in Rust I might use iter().collect() or whatever.


I was curious what it looked like where I work, because I mostly encounter `make([]T, 0, n)` in codebases I've touched, so I did a quick grep...

And the results were roughly 6,000 cases of `make([]T, n)` vs 5,000 cases of `make([]T, 0, n)`, ignoring most generated files (afaict), allowing basically anything but `,` for `n`, and requiring `...)$` for regex simplicity. I didn't read all the results, but the couple hundred I did check in both looked reasonable, so it's probably not too inaccurate.

I'm not sure how representative that is of go code in general, but I think I can be reasonably confident in claiming that neither is a consistent preference.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: