I think for most intents and purposes, option types and Kotlin’s approach are more or less equivalent. Either way, the compiler helps you avoid null dereference errors.
I like Swift’s approach personally, which is that there’s an Option type, but loads of syntax sugar to make working with it easy (just append a “?” after the type to flag it as optional, “if let”, optional chaining with “?.”, “?()”, etc etc.)
For Go's purposes, though, they aren't equivalent at all.
Option types require generics, which Go doesn't (currently) have and may or may not be enthusiastically embraced by the community.
Option types must also be baked into the language, standard library and culture from the beginning in order to be ergonomic; otherwise you're constantly having to wrap and unwrap them whenever you interact with code that was written before the type was introduced. Which is most the code you interact with.
Finally, my own experience has been that Option types generally make things more rather than less complicated when you introduce them to a language that already has null. You'll need to make a decision on whether Some(null) is an allowed value, both options will introduce language warts.
Kotlin's approach, on the other hand, does not require generics to work, and interacts very well with the JVM's existing libraries and its existing type system. It's not going to butter everyone's toast. You can't do anything monadic with Kotlin's approach, for example, but I don't get the impression that the Go community is just desperate for monads.
I suppose it wouldn't. But, if you're going to do it as a feature that's built into the core language, I'd say that's even more reason to just do it Kotlin-style. The other main downside of doing it that way is that it needs to be baked into the core language and can't be pushed out to the standard library the way you can with optional types. But that wouldn't really be a practical difference compared to an optional type implemented without full-fledged generics.
The other big distinction between the Kotlin approach and optional types is that the Kotlin approach introduces no new run-time types. Null safety is checked statically, and then you're done. That's a big part of why it plays nicer with an existing standard library. It also means, though, that you introduce no extra run-time overhead, which I would assume is something that's considered pretty desirable to gophers.
They're not quite the same. With option types `Some(x)` is a distinct type and value to `x`. That's not true in e.g. Kotlin or Dart. For example this is fine in Dart:
void foo(int? x) {}
void main() {
foo(5);
}
This is not fine in Rust:
fn foo(x: Option<i32>) {}
fn main() {
foo(5);
}
You might not think that makes much difference, but consider if `foo()` starts off as `fn foo(x: i32)` and after using it 10k different places you want to change it to `fn foo(x: Option<i32>)`. That's a backwards compatible change in Dart (and I presume Kotlin), but not in Rust.
I like Swift’s approach personally, which is that there’s an Option type, but loads of syntax sugar to make working with it easy (just append a “?” after the type to flag it as optional, “if let”, optional chaining with “?.”, “?()”, etc etc.)