What you are asking for is captured in https://golang.org/issue/7054
On Tuesday, August 22, 2017 at 12:28:41 PM UTC-7, Steven Blenkinsop wrote: > > Other places where Go relies on every type having a zero value: > > // Making slices with non-zero length. > s := make([]*int, 10) > > // Reslicing a slice beyond its length. > s := make([]*int, 0, 10)[:10] > > // Eliding fields from a composite literal. > p := struct { x: int; y: *int } { x: 5 } > s := []*int { 10: new(int) } > > // Initializing an array programmatically. > var arr [10]*int > for i := range arr { ... } > > // Accessing a non-existent map entry. > v := m["non existent"] > > // Reading from a closed channel. > v := <-ch > > // Comma-ok. > // Without zero values, the type of `v` is in each case > // something like `ok ? *int : uninitialized`. > v, ok := m["string"] > v, ok := i.(*int) > v, ok := <-ch > > > On Tue, Aug 22, 2017 at 8:59 AM <gurp...@gmail.com <javascript:>> wrote: > >> I would like to echo on Tong Sun's suggestion here. I know his isn't an >> "experience report" per se, but a suggestion worth building on, for those >> who're wishful of optionals in Go. >> >> The case mentioned might be immediately solvable by just using a pointer >> to the variable, which gives you the ability to assign nil (json null) to >> it. However, *T is *not* syntactic sugar for Optional<T>. Pointers come >> across as "just as good as optionals" when needed because we don't have >> another [built-in] option. Not to mention, pointers have more than >> nil-assignability to them. >> >> I understand that we can just write a generic generator for Optional<T> >> for whatever type we want an optional wrapper for. This is something I've >> always done when absolutely needed (most of the time with proto3 Protobuf). >> >> func main() { >> msg := pboptional.NewString() >> >> fmt.Println("msg:", msg). // => msg: nil >> >> msg.From("hello world") >> >> fmt.Println("msg:", msg) // => msg: Optional("hello world") >> >> if msg, ok := msg.Unwrap(); ok { >> // some >> fmt.Println("msg:", msg) // => msg: hello world >> } else { >> // none >> fmt.Println("msg is nil") >> } >> } >> >> There are obvious advantages to using optionals, including safely >> defining variable. However, on the contrary, Go is currently, and by-design >> so, not in the best shape to adopt optional types. For optionals to be a >> viable in core, non-optionals would have to (?) guarantee a value (and not >> just assumed zero-value when left uninitialized). This is for the compiler >> to deliver the type-safety promise of optionals *and* non-optionals. In >> other words, it means that we would have to not allow uninitialized types >> to be zero-value. I mean, what good is supporting optional types, if the >> non-optionals don't require you to set their values? >> >> Consider this currently valid Go code: >> >> func getAge() (int, error) { >> var age int >> return age, errors.New("ERR") // age is assumed zero-value >> } >> >> func main() { >> age, err := getAge() // => 0, ERR >> } >> >> With optionals implemented (how I'm imagining), this would become: >> >> // uninitialized non-optional should not compile >> // i.e. don't assume zero-value >> func getAge() (int, error) { >> var age int >> return age, errors.New("ERR") // => compile error: variable age is >> not initialized >> } >> >> // this should work instead >> func getAge() (int?, error) { >> var age int? >> return nil, errors.New("ERR") >> } >> >> func main() { >> age, err := getAge() // => Optional(nil), ERR >> } >> >> But every method that also returns an error, should not necessarily have >> an accompanied optional type, like `(int?, error)`. There's so much in Go >> that can be nil (or nil like zero-values), and isn't necessarily fit to be >> considered optional, like nil interfaces and pointers. >> >> We're also going to have to reconsider the phrase "errors are just >> values" if we want to pair non-optional types with error in the return >> types. Take the following suggestion (inspired from Swift): >> >> func getAge() (int, throws error) { >> var age int >> throw errors.New("ERR") >> // we're not returning anything and it compiles >> // i.e. throw *is* return but only for error >> } >> >> func main() { >> age := try getAge() // => panic("ERR") >> } >> >> func main() { >> // although getAge() returns a non-optional, it >> // gets is automatically wrapped in an optional >> // when using `try?`. >> // >> // basically we're trading error for nil value. >> age := try? getAge() // => Optional(nil) >> } >> >> func main() { >> // this is the graceful way to get non-optional result >> // and handle error, if any. >> try { >> age := getAge() >> } catch error { >> fmt.Println(err.Error()) // => ERR >> } >> } >> >> Therefore, if considered, optionals would be a *huge* undertaking to >> implement (and practice) in Go source, while also delivering the promise >> optionals bring. >> >> Let me know if you have a better syntax/suggestion than try catch blocks >> (for returning only an error; no zero-values for non-optionals). >> >> I think an ideal first step would be the community blessing and adopting >> en masse some Optional<T> "generator". Second step would be to vouch for >> generics with this use case. And then implement an actual generic like >> `type Optional<T> struct { Value T; HasValue bool }`. And then perhaps, as >> the fourth or so step, we may shape our coding practices to better >> understand how all this could be practiced in Go source itself. >> >> -- >> Gurpartap Singh >> https://twitter.com/Gurpartap >> >> On Saturday, August 19, 2017 at 8:35:34 PM UTC+5:30, Tong Sun wrote: >>> >>> Suggesting C# type syntax like "int*?*" so as to take nil as valid >>> value. >>> >>> Currently: >>> >>> var i int >>> i = nil >>> >>> will give: >>> >>> cannot use nil as type int in assignment >>> >>> However, more and more people are using json to transport data, and >>> there will be times that json may be invalid. I.e., the "int" type has >>> 'null' as input. >>> >>> This is causing tremendous problems for me so far, as I have to jump >>> over the hoops to deal with them. >>> In C#, just by adding a "?" to the end of the type solves the problem. >>> >>> Please consider. >>> >>> >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com <javascript:>. >> For more options, visit https://groups.google.com/d/optout. >> > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.