-1

In golang, you can fetch a key from a map using the obvious syntax:

someMap := map[string]string{
   //... contents
}

value := someMap["key1"]
// If "key1" exists in someMap, then the value will be returned; else empty string.

Problem: You can't tell missing keys apart from legitimate empty string values

So, you can test for presence using the comma ok idiom

value, ok := someMap["key1"]
if ok {
   // we know that "key1" was in the map, even if value is empty string
} else {
   // we know that "key1" was NOT in the map
}

What this looks like is that there are two different overloads of the map lookup method, one which returns just a single map value result, and one which returns the (value, bool) result, and the compiler seems to be selecting the overload based on how many return values you've said you'd like to receive.

This is quite nice, and I was wondering if it was possible to implement this on my own functions?

E.g:

func fetchValue() (string, bool) {
    return "", true
}

func testMain() {
    // This works fine, as expected
    val, ok := fetchValue()
    if ok {
        fmt.Println(val)
    }

    // COMPILE ERROR: Assignment count mismatch: 1 = 2.
    val2 := fetchValue()
}

// COMPILE ERROR: fetchValue redeclared in this package
func fetchValue() string {
    return ""
}

Is this possible? or is it secret special language sauce that only works for the builtin map type and nothing else?

Orion Edwards
  • 121,657
  • 64
  • 239
  • 328
  • 4
    In short: the special syntax with maps and channels are backed by the language spec, you can't create functions that may be used the same. – icza Aug 10 '22 at 09:47
  • 1
    There are a few places in the specs where you can see this "two possible assignments" feature, like getting a value from a map (your question), iterating over an array or a map, dynamically casting an interface to a concrete type. In that last case, the difference is even more blatant : the 1-value assignment may panic, while the 2-values assignment never panics. These are all built-in features and can't be implemented with your own code. – LeGEC Aug 10 '22 at 09:56

1 Answers1

2

You cannot define your own function that sometimes returns 2 values, sometimes 1.

You can do:

val, ok := fetchValue()
if !ok {
    // failure path.
}

or

val, _ := fetchValue()
// not checking for failure.
Hymns For Disco
  • 7,530
  • 2
  • 17
  • 33