What else is in Go 1.11?
talks.godoc.org
talks.godoc.org
1) proper dependencies management system (the new module system might address this) and
2) gener... nah, just kidding -- actually null protection. I don't want to see another segfault or null pointer failure ever again.
If it had these two features, I'd probably stop toying around with Rust and Crystal and just use Go. Unfortunately, 2) is probably impossible without seriously breaking old code, and they're not gonna break old code.
A language as simple as Go without nilable types would be great, though.
I've seen a raw SIGSEGV in Go due to a runtime bug years ago, and the only safe outcome is process termination.
On the other hand, dereferencing a nil value in Go in relatively safe (as in Java), all it does is crash the goroutine. For common cases like HTTP and RPC handlers, no big deal, safely recoverable.
Edit: on second thought, forget that. I agree that it's not a good thing (not safe) for recovery from goroutine crash to be possible.
Yeah, these are exactly the things I don't want to see: production log messages saying that something or other referred to a nil pointer and thus crashed some process. I don't think they belong to modern programming.
Sure, segfaults are even worse since you don't even get the log message, but I still kinda lump both of these problems together as "errors from the 1900s that shouldn't happen anymore".
Are the complications due to null protection being there, or are they due some other things?
Just “value” -> Maybe String
Nothing -> Maybe a
If your function returns a “Maybe String”, it can either be just a value, or Nothing. However, if a function returns a “String”, you can’t return Nothing, only an actual String.There’s no null in Haskell.
rust is hardly the first one, too.
No.
> There must be something to designate a missing value, a non assigned pointer or reference
Option types are something like 45 years old, they're not exactly futuristic technology.
This achieves two things:
1. It allows you to define functions that cannot return NULL, and the compiler guarantees this. This is a huge win - you no longer have NULL as a possible return value for many functions.
2. Values belonging to the option type have to be unwrapped to access their contents, so it's not possible to unknowingly dereference a missing value. This is an even bigger win than #1, because it can literally eliminate null pointer errors.
A caveat to #2 is that depending on the language, it may be possible to override safety, for example Haskell's fromJust can throw an exception if used on a missing value. But this tends to require conscious effort, and can easily be checked for automatically, since it involves the use of unsafe function calls.
A much scarier example there is C++, where std::optional can be deref'd (literally `*opt`, the easiest and shortest thing you can do with it)… and just UBs on an empty optional. Because C++ hates both type-safety and memory-safety.
Nil exception handling is horrible in go. The thing wasn’t designed to handle pointers and blows up left and right once someone tries to use them (or untyped objects).
Dependency management is a total mess.
There's a great blog post series about it (though it's dense, plan to spend a few hours to read it all: https://research.swtch.com/vgo)
Maybe for Go 2.0.
2. because sets are significantly less useful without set-operations (intersections, unions, differences) and since go does not have user-defined generics you can't build a generic version of those (
3. because it wastes 1 byte per item (according to the comments in bmap, buckets are implemented column-major
`map[K] struct{}` would fix 3 and the second half of 1 (struct{} is a zero-sized singleton) but is somewhat less ergonomic so the impact of what's left of 1 is worse, and it doesn't solve 2 at all
AFAIK the reason — much like C# — is their adherence to the concept of ubiquitous defaults / zero values: as far as Go is concerned all types have a zero-value (a non-overridable default value when not explicitly initalised), and as far as its community is concerned zero values are a good thing and must be embraced.
Default zero without it being opt-in is terrible.
> but default zero pointer… ugh
That's what ubiquitous default zero gets you.
But the more interestingly problem is how Go's struct "constructor" works. It is very low-level, you just assign some fields in a struct like &SomeStruct{X: 1, Y: "y"}; you can also assign all fields, in which case you can omit the keys, like &SomeStruct{1, "y"}. let's call those the key-value variant and positional variant of "free-form constructor".
You can provide a "function constructor", which is simply a function that returns SomeStruct or * SomeStruct, but it is not required, nor can you forbid the free-form constructor.
This is in stark contrast with, say, Java, where the function constructor is both required and the only allowed form. That makes it easy to make sure that non-nullable pointer fields are always initialized, because the compiler only needs to check the constructors.
In Go it is much harder. You can make the free-form constructor check that non-nullable pointer fields get initial values, but then Go has this promise that the author of a struct can add new fields without breaking users of the free-form constructor, as long as they are using the key-value variant instead of the positional variant. So if a struct was originally:
type SomeStruct { X int Y string }
A user can make an instance with &SomeStruct{X: 1, Y: "y"}. If the author of the struct decides to add a new field, the code should still work. That should be the case even if the new field is a non-nullable pointer field. This now defeats the purpose of non-nullable pointer fields.
This is the bit that would need to change. And actually, doing so would provide the same benefits that non-nullable types do in other contexts.
Say a Go library user is using a struct in 5 places, and the library author adds a new field. The user updates the free-form constructor to properly initialise the new field in 4 of those 5 places, but overlooks the 5th. As it stands, that will fail silently if the program is relying on using a non-null value somewhere else in the code. If upgrading the library caused a compile time error then that bug would have been caught.
Rust also has "free-form constructors" like Go, and this is the approach it takes: you must provide a value for all fields.
Rust has a half backed support for default initialization, where you can either mark all fields as default initialized via a macro or none (or you can mark them and add a constructor that only changes some, but then the API is confusing for clients unless default initialization is a valid construction). This means that it’s much more common to write constructors, and being forced to set many fields to 0, empty string, None, ecc. is tedious and factually useless; the provide support (Default macro) is not powerful enough to avoid this, unfortunately.
I strongly prefer Go’s approach to default initialization in general, and I think it is orthogonal to non-nullable types (you could have both and save the day). For instance, I don’t see what we lose in Rust by saying that integers auto-initialize to zero unless you name them in the constructor.
So it has half-baked support because… you can opt into exactly how Go behaves but it's not foisted upon you?
> This means that it’s much more common to write constructors, and being forced to set many fields to 0, empty string, None, ecc. is tedious and factually useless; the provide support (Default macro) is not powerful enough to avoid this, unfortunately.
Be the change you want to see in the world and open an RFC for partial defaulting?
It's already possible to "fill in" literal struct with `..Default::default()`, if you can defend there being a use-case for it, this would be extendable to filling in default-able fields even without an explicit (and public) Default implementation for the struct. There was an issue on the tracker in the past (https://github.com/rust-lang/rust/issues/42692) but the change is big enough that it would require an RFC, actual design and consensus, but that's the extent of it.
Alternatively, build a macro doing that for you. There might already be one but a quick cargo search didn't turn anything up.
> I strongly prefer Go’s approach to default initialization in general, and I think it is orthogonal to non-nullable types (you could have both and save the day).
How can you have non-nullable fields with a zero value exactly?
> For instance, I don’t see what we lose in Rust by saying that integers auto-initialize to zero unless you name them in the constructor.
The regularity of the language to start with.
Non-nullable pointers don't make struct creation any more expensive.
> You can provide a "function constructor", which is simply a function that returns SomeStruct or * SomeStruct, but it is not required, nor can you forbid the free-form constructor.
You can have an exported function returning a non-exported type. This restricts the "freeform" constructor to the package's internal's. It severely limits the caller's ability to use it (unless you also provide an interface to work with), but it's there.
I don't ask for much. I just want a GC'd Rust (one of the few modern languages that has option types in the std lib) or an F# that isn't tied to the .NET standard lib. Please?
F# is basically OCaml on .Net, so… OCaml?
> I don't understand how language developers don't prioritize package management in 2018
As you already know, Ocaml already has a decent package manager opam, this same situation will happen in any language where the packages get stale(e.g. in rust you installed something used nightly features that didn't make it mainstream).
(the pipe operator is another favorite I miss often)
I think they’re doing a compiler rewrite that steals the good ideas from Rust (like good error messages).
What? Are they removing “godoc <pkg>”? I used that a lot as a man page. It’s especially useful when you don’t have internet access
Edit: it’ll still be available in `go doc`, just that `godoc` will only be a web server. https://tip.golang.org/doc/go1.11#godoc
https://raw.githubusercontent.com/mvdan/talks/master/2018/go...
"""Note that these kinds of minor updates to gofmt are expected from time to time. In general, we recommend against building systems that check that source code matches the output of a specific version of gofmt. For example, a continuous integration test that fails if any code already checked into a repository is not “properly formatted” is inherently fragile and not recommended."""
As a frequent repo/commit spelunker, I'm gonna have to disagree here. It is better to have this changed all in one commit instead of tacking on that formatting change along with an unrelated change elsewhere in the file and doing that all over the place at separate times. What's inherently fragile (formatting wise) is making a change to a file that does not meet the current formatting requirements and then having it format on save/commit, messing up blames, code review diffs, etc.
Ideally the format would never change at all. An occasional change-the-world update is a reasonable compromise, but it should be done as a single commit with no logic changes.
Server-side you have the check.
Client-side you have a hook that runs gofmt when you commit, and in principle you’ll never hit the server-side check.
Just in case something goes wrong -- and something somewhere always goes wrong -- you don’t want the server to silently rewrite stuff on your behalf.
- WebAssembly and Modules have already been covered.
Note that support is still experimental, so if you want stability, it is advised to remain inside GOPATH for another release. This is a good post - https://systemdump.io/posts/2018-07-22-go-modules
However, do please feel free to try it out and file bugs.
Ultimately though I don't really care all that much. Everyone will fix it in a few commands, and everything will be green again.
I have to do this all the time when 'git blame -wM' doesn't give me what I want when looking at kernel changes.
I can see that the slides alone aren't self-explanatory in some points, for example with the random byte reading or gofmt. I'll make sure to link to the issues/CLs in the slides next time :)
Well it’s called libSystem.dylib :) but, still, good. It looks like this was only done in “runtime” but hopefully the rest can come in 1.12. [1]
Can someone explain how this is a feature?
https://go-review.googlesource.com/c/go/+/64451
> Code has ended up depending on things like RSA's key generation being deterministic given a fixed random Reader. This was never guaranteed and would prevent us from ever changing anything about it.
That's a bit disturbing, since Go's test caching can be a bit of a nuisance. I did some quick Googling, but couldn't find an explanation.
if you want to rebuild without cache; go clean -cache && go build