Skip to content

proposal: Go 2: add ?? operator to select first non-zero value #37165

Closed
@earthboundkid

Description

@earthboundkid

It is often asked why Go does not have a ternary operator. The Go FAQ says,

The if-else form, although longer, is unquestionably clearer. A language needs only one conditional control flow construct.

However, technically Go has a second form of control flow:

func printer(i int) bool {
    fmt.Println(i)
    return i%2 != 0
}

func main() {
    _ = printer(1) && printer(2) && printer(3)
    // Output: 1\n2\n
}

I believe that many of the usecases that people want a ternary operator for could be covered by adding a ?? operator that is similar to && but instead short-circuit evaluates non-boolean expressions while the resulting value is a zero-value.

For example, these two snippets would be identical:

port := os.Getenv("PORT")
if port == "" {
    port = DefaultPort
}
port := os.Getenv("PORT") ?? DefaultPort

Another use case might be

func New(c http.Client) *APIClient {
    return &APIClient{ c ?? http.DefaultClient }
}

In general, ?? would be very useful for setting default values with less boilerplate.

Another use for ?? might be

func write() (err error) {
    // ...
    defer func() {
        closeerr := w.Close()
        err = err ?? closeerr
    }()
    _, err = w.Write(b)
    // ...
}

Some rules: ?? should only work if all expressions evaluate to the same type (as is the case for other operators), and ?? should not work for boolean types, since that would cause confusion in the case of a pointer to a bool. If/when Go gets generics, you can trivially write first(ts ...T) T, so the operator is only worth adding to the language if it has short-circuit evaluation.

In summary, ternary is notoriously unclear, but ?? would not be any more unclear than &&. I believe it would be more clear than an equivalent if-statement since it would more clearly express the intent of setting a default, non-zero value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions