I'm curious why this is not implemented as a method on the map type (and others like list) instead of being a top-level builtin. I suppose it is consistent with other collection operations such as append and len... which I guess makes me wonder why those are builtins as well.
The answer is lack of generics in all previous versions of Go. There's no way to express a generic interface to have methods for map or slice (which are not interfaces, but compiler magic instead). All the operations on builtin types must be implemented as globals handled by the compiler.
Been using Go since the early days, and 'make/append' always felt clunky and out of place. Especially when you could just use literals for a map/slice...
> Been using Go since the early days, and 'make/append' always felt clunky and out of place. Especially when you could just use literals for a map/slice...
Most people do use the literals for creating the empty map/slice. "make" is mostly useful when specifying a known length or capacity, which saves unnecessary allocations and improves performance.
"We talked about defining maps.Clear in #55002, but how? It would not be possible to write in pure Go code. Instead it would need some kind of hidden entry point into the runtime.
In the past I've referred to that kind of library change as a "back-door language change", meaning it's a language change - it adds something not possible in pure Go - but pretends not to be one. We try hard to avoid doing that."
> We debated this issue but decided implementing len and friends as functions was fine in practice and didn't complicate questions about the interface (in the Go type sense) of basic types.
I imagine similar reasoning applies to "clear" here.
That's a pretty weird rationale IMO. "It doesn't break anything" should be the minimum requirement for a major design choice, but it certainly isn't sufficient on its own. They sort of imply that making it a method would "complicate questions about the interface of basic types", but I don't really understand what that would even mean "in the Go type sense". Are they worried that someone might make an interface with a `Len` method and therefore be able to pass slices and maps to it? That honestly seems like a feature, not a bug, and certainly not worth throwing out the nicer syntax for.
When you create a new type like this, you lose all methods from the original type. If the delete operation was implemented as a method on the `map` type, `Header.Del` would need to convert back to a `map` type to call it.
Interesting, I was aware of that newtype wrapper pattern, but I did not realize that methods weren't automatically forwarded to the wrapped type. This isn't the design I'd personally choose, but it does seem more consistent with what I know of Go's philosophy now that I understand this.
It's hard to articulate but whenever I find myself wishing I could inherit methods in a wrapper type, the design is bad. The designs where it ends up not being necessary are always much friendlier.
Yeah, I don't think I disagree there. If you want to automatically delegate methods, you can always use a type alias, and if you want to have delegation but type strictness (i.e. not having the alias and the original being interchangeable), you can do it manually. I think the two things here that I personally don't prefer are not having some way to opt into delegation (e.g. the `Deref`/`DerefMut` traits in Rust) and the more general paradigm of interfaces being implicit (which if I understand correctly is why it would be ambiguous about whether the wrapper types implemented the same interfaces as the wrapped type), but those are much larger philosophical differences. If you do want interfaces and wrapper types to work the way they do in Go, I agree that having a method for length would probably be less consistent with the design philosophy.
I do feel like the FAQ could be a bit more explicit about the rationale though; most people who read that page and have that question aren't going to as experienced in Go, so they aren't as likely to read "interfaces on basic types" and go "aha, yes, that would be weird with wrapper types!". That said, I also don't really use Go at all due to the philosophical differences I mentioned above, so maybe my reading isn't going to be representative of their target audience anyhow.
Most obvious flaw in Go is the top-level bs. Why on earth are they adding things to that? It is off course down to other poor decisions made historically that forces this design. But anyway. They should fix the lang and scrap the top-level nonsense all together.
For a beginner in Go it makes absolutely no sense at all. Most of the builtins should be methods.