How to understand the golang multi-return value - go

Golang supports assigning multiple return values to multiple left hand side variables. E.g:
func test() (string, string) {
return "1", "1"
}
a, b := test()
or
a, _ := test()
and the number of receiving variables and return values must match:
b = test() //wrong
But for some built-in types, such as [] or <-, a variable number of return values are supported
key, exist := map[key]
key := map[key]
I can read value from channel like this
c <- myChan
c, exist <- myChan
How can we explain the inconsistency? Is this a capability reserved to the core go runtime/language?

This behavior clearly specified in the golang specification:
Receive operator
A receive expression used in an assignment or initialization of the special form
x, ok = <-ch
x, ok := <-ch
var x, ok = <-ch
var x, ok T = <-ch
yields an additional untyped boolean result reporting whether the communication succeeded. The value of ok is true if the value received was delivered by a successful send operation to the channel, or false if it is a zero value generated because the channel is closed and empty.
Index expression
An index expression on a map a of type map[K]V used in an assignment or initialization of the special form
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
yields an additional untyped boolean value. The value of ok is true if the key x is present in the map, and false otherwise.
Assignments
A tuple assignment assigns the individual elements of a multi-valued operation to a list of variables. There are two forms. In the first, the right hand operand is a single multi-valued expression such as a function call, a channel or map operation, or a type assertion. The number of operands on the left hand side must match the number of values. For instance, if f is a function returning two values,
x, y = f()
assigns the first value to x and the second to y. In the second form, the number of operands on the left must equal the number of expressions on the right, each of which must be single-valued, and the nth expression on the right is assigned to the nth operand on the left.
Therefore as you can see this behavior being specified by language design and you cannot achieve those specified for Receive operator and Index expression by yourself.

You are confusing multiple values returned from a function with the so-called "comma ok" idiom.
With a function's return values you must either handle all of them, or none of them. Simple.
"Comma ok" is more subtle. Often the behavior is changed if you have a second value specified. Consider these statements:
v, ok := x.(int)
// vs
v := x.(int)
If x is an interface holding an integer, all is well, however, if x holds a different type the first statement will work (returning 0, false), and the second one will panic.
Each type of statement with a "comma ok" form is a different special case, and they are not the same as other kinds of multiple assignments (such as multiple function return values). You cannot compare them, each is its own thing, with its own rules.

Related

What is the result of a single variable expression evaluation

Running the following snippet of Go code one can realize that function foo receives the value of the first argument actually set while evaluating the second argument of the function. This behavior might look counterintuitive so that we need to prove this to be a part of language spec, not something implementation-specific.
package main
import (
"fmt"
)
func setVal(s *int, v int) int {
old := *s
*s = v
return old
}
func foo(s int, p int) {
fmt.Printf("s = %d, p = %d\n", s, p)
}
func main() {
var s int
foo(s, setVal(&s, 99))
}
Programm outputs s = 99, p = 0, which means a modified value of variable s has been passed to the function.
Here is what the Go spec says regarding the case.
In a function call, ...arguments must be single-valued expressions ... arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function... Where usual order is the lexical left-to-right order.
A variable is a storage location for holding a value. ...A variable's value is retrieved by referring to the variable in an expression; it is the most recent value assigned to the variable.
Therefore foo(s, setVal(&s, 99)) is a function call, variable s and function setVal() are the single-valued expressions, and s is evaluated first. The last spec statement makes one assume the result of a variable evaluation is its value, so if that is true, function foo should receive initial value of the variable s.
But it in fact it appears that the function receives the value of the first argument been set at the moment of evaluating the second argument, which is a bit confusing.
Does that mean the evaluation order is broken or the result of a variable evaluation is not its value?
What you "miss" from the spec is Spec: Calls:
In a function call, the function value and arguments are evaluated in the usual order. After they are evaluated, the parameters of the call are passed by value to the function and the called function begins execution.
Evaluating the parameters does not mean their values are read or "taken". The first parameter is s, its evaluation is s itself, but its value is not yet read. The second parameter is evaluated, which means setVal() is called and will modify the value of s.
Now that we have evaluated the parameters, their values are read, so s will have the value 99.
Evaluating s in the example is trivial, but of course that could be a more complex expression just like the second argument. Here's a more complex example:
s, s2 := new(int), new(int)
getFunc := func() func(s int, p int) { return foo }
first := func(a, b *int) *int { return a }
getFunc()(*first(s, s2), setVal(s, 99))
Call of the last function involves the following steps:
function value is evaluated: getFunc() is called, it's return value will be the function value
parameters are evaluated:
(a) first() is called, its return value is dereferenced;
(b) setVal() is called, its return value will be used
And now the values are taken: value of *s and the old value of s (value returned by setVal()).
This will output the same as your example, try it on the Go Playground.

List of cases in Go that allow omitting an optional second returned value

When calling functions or methods with multiple return values, the caller, if unpacking any return values, must unpack them ALL.
f, err := os.Open("filename")
The err variable must be either declared or ignored with the blank identifier _, but it cannot be omitted.
However, there are some operations built into the language, which allow one to omit the optional second return value.
Is there a more or less formal list of situations where an operation with a data structure or a function call returns a second value that is optional and can be ignored by only receiving the first return value? For example:
m := make(map[string]int)
v, ok := m["hello"]
The ok variable is entirely optional and can be omitted.
v := m["hello"]
Likewise, with channels:
v, ok := <-ch
or
v := <-ch
Are there any other cases of that behavior beyond the two above?
The expressions with optional values when used in an assignment or initialization are: type assertion, map index and channel receive.
The specification does not have a formal list of these expressions, but the expressions are all described in the specification.

Transitive property in Golang

This piece of code looks quite counter-intuitive to me:
var first *byte
var second interface{}
fmt.Println(first, first == nil) // <nil> true
fmt.Println(second, second == nil) // <nil> true
fmt.Println(first == second) // false
As far as I understand, the case is that the first variable is a pointer to an empty variable of type byte, whereas the second is an empty interface. So, as the variables are not the same type, they are not considered equal.
But if they are not equal to each other, how can they be equal to some third value? Is it common situation in programming languages when Transitive Law is not held?
The identifier nil represents the zero value for channel, pointer, interface, function, map and slice types.
The zero value for a *byte is not equal to the zero value for an interface{}.
Nil does represent a zero value, but each value in go also has a type.
I have also seen something similar to this in testing when methods return a custom error type as err, and then check to see if the errors are equal which fails because Go intrinsically believes they are different because you have not type asserted it to the custom error type.
Here's a more interesting example of intransitivity of Go's == operator. It doesn't rely on nil; for types like functions and maps, x==nil is best thought of as an special operator, since values of those types aren't comparable to each other.
// "hello" != x == s == "hello"
func main() {
type S string
var s S = "hello"
var x interface{} = s
fmt.Println(s == "hello") // s == "hello"
fmt.Println(x == s) // x == s
fmt.Println(x == "hello") // x != "hello"
}
One way to explain this anomaly is that there are really two different equality operators at work here. The first comparison has type S, but the second and third have type interface{}. Once the types are erased, the interface conversions become explicit and each "==" is replaced by the appropriate comparison operator for its type. Those comparison operators, individually, are true equivalence relations, which is to say they are transitive.

Checking if key exist in map which return interface type in go [duplicate]

I know I can iterate over a map m with
for k, v := range m { ... }
and look for a key, but is there a more efficient way of testing for a key's existence in a map?
Here's how you check if a map contains a key.
val, ok := myMap["foo"]
// If the key exists
if ok {
// Do something
}
This initializes two variables. val is the value of "foo" from the map if it exists, or a "zero value" if it doesn't (in this case the empty string). ok is a bool that will be set to true if the key existed.
If you want, you can shorten this to a one-liner.
if val, ok := myMap["foo"]; ok {
//do something here
}
Go allows you to put an initializing statement before the condition (notice the semicolon) in the if statement. The consequence of this is that the scope ofval and ok will be limited to the body of the if statement, which is helpful if you only need to access them there.
In addition to The Go Programming Language Specification, you should read Effective Go. In the section on maps, they say, amongst other things:
An attempt to fetch a map value with a key that is not present in the
map will return the zero value for the type of the entries in the map.
For instance, if the map contains integers, looking up a non-existent
key will return 0. A set can be implemented as a map with value type
bool. Set the map entry to true to put the value in the set, and then
test it by simple indexing.
attended := map[string]bool{
"Ann": true,
"Joe": true,
...
}
if attended[person] { // will be false if person is not in the map
fmt.Println(person, "was at the meeting")
}
Sometimes you need to distinguish a missing entry from a zero value.
Is there an entry for "UTC" or is that 0 because it's not in the map
at all? You can discriminate with a form of multiple assignment.
var seconds int
var ok bool
seconds, ok = timeZone[tz]
For obvious reasons this is called the “comma ok” idiom. In this
example, if tz is present, seconds will be set appropriately and ok
will be true; if not, seconds will be set to zero and ok will be
false. Here's a function that puts it together with a nice error
report:
func offset(tz string) int {
if seconds, ok := timeZone[tz]; ok {
return seconds
}
log.Println("unknown time zone:", tz)
return 0
}
To test for presence in the map without worrying about the actual
value, you can use the blank identifier (_) in place of the usual
variable for the value.
_, present := timeZone[tz]
Searched on the go-nuts email list and found a solution posted by Peter Froehlich on 11/15/2009.
package main
import "fmt"
func main() {
dict := map[string]int {"foo" : 1, "bar" : 2}
value, ok := dict["baz"]
if ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
}
Or, more compactly,
if value, ok := dict["baz"]; ok {
fmt.Println("value: ", value)
} else {
fmt.Println("key not found")
}
Note, using this form of the if statement, the value and ok variables are only visible inside the if conditions.
Short Answer
_, exists := timeZone[tz] // Just checks for key existence
val, exists := timeZone[tz] // Checks for key existence and retrieves the value
Example
Here's an example at the Go Playground.
Longer Answer
Per the Maps section of Effective Go:
An attempt to fetch a map value with a key that is not present in the map will return the zero value for the type of the entries in the map. For instance, if the map contains integers, looking up a non-existent key will return 0.
Sometimes you need to distinguish a missing entry from a zero value. Is there an entry for "UTC" or is that the empty string because it's not in the map at all? You can discriminate with a form of multiple assignment.
var seconds int
var ok bool
seconds, ok = timeZone[tz]
For obvious reasons this is called the “comma ok” idiom. In this example, if tz is present, seconds will be set appropriately and ok will be true; if not, seconds will be set to zero and ok will be false. Here's a function that puts it together with a nice error report:
func offset(tz string) int {
if seconds, ok := timeZone[tz]; ok {
return seconds
}
log.Println("unknown time zone:", tz)
return 0
}
To test for presence in the map without worrying about the actual value, you can use the blank identifier (_) in place of the usual variable for the value.
_, present := timeZone[tz]
Have a look at this snippet of code
nameMap := make(map[string]int)
nameMap["river"] = 33
v ,exist := nameMap["river"]
if exist {
fmt.Println("exist ",v)
}
As noted by other answers, the general solution is to use an index expression in an assignment of the special form:
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
var v, ok T = a[x]
This is nice and clean. It has some restrictions though: it must be an assignment of special form. Right-hand side expression must be the map index expression only, and the left-hand expression list must contain exactly 2 operands, first to which the value type is assignable, and a second to which a bool value is assignable. The first value of the result of this special form will be the value associated with the key, and the second value will tell if there is actually an entry in the map with the given key (if the key exists in the map). The left-hand side expression list may also contain the blank identifier if one of the results is not needed.
It's important to know that if the indexed map value is nil or does not contain the key, the index expression evaluates to the zero value of the value type of the map. So for example:
m := map[int]string{}
s := m[1] // s will be the empty string ""
var m2 map[int]float64 // m2 is nil!
f := m2[2] // f will be 0.0
fmt.Printf("%q %f", s, f) // Prints: "" 0.000000
Try it on the Go Playground.
So if we know that we don't use the zero value in our map, we can take advantage of this.
For example if the value type is string, and we know we never store entries in the map where the value is the empty string (zero value for the string type), we can also test if the key is in the map by comparing the non-special form of the (result of the) index expression to the zero value:
m := map[int]string{
0: "zero",
1: "one",
}
fmt.Printf("Key 0 exists: %t\nKey 1 exists: %t\nKey 2 exists: %t",
m[0] != "", m[1] != "", m[2] != "")
Output (try it on the Go Playground):
Key 0 exists: true
Key 1 exists: true
Key 2 exists: false
In practice there are many cases where we don't store the zero-value value in the map, so this can be used quite often. For example interfaces and function types have a zero value nil, which we often don't store in maps. So testing if a key is in the map can be achieved by comparing it to nil.
Using this "technique" has another advantage too: you can check existence of multiple keys in a compact way (you can't do that with the special "comma ok" form). More about this: Check if key exists in multiple maps in one condition
Getting the zero value of the value type when indexing with a non-existing key also allows us to use maps with bool values conveniently as sets. For example:
set := map[string]bool{
"one": true,
"two": true,
}
fmt.Println("Contains 'one':", set["one"])
if set["two"] {
fmt.Println("'two' is in the set")
}
if !set["three"] {
fmt.Println("'three' is not in the set")
}
It outputs (try it on the Go Playground):
Contains 'one': true
'two' is in the set
'three' is not in the set
See related: How can I create an array that contains unique strings?
var d map[string]string
value, ok := d["key"]
if ok {
fmt.Println("Key Present ", value)
} else {
fmt.Println(" Key Not Present ")
}
var empty struct{}
var ok bool
var m map[string]struct{}
m = make(map[string]struct{})
m["somestring"] = empty
_, ok = m["somestring"]
fmt.Println("somestring exists?", ok)
_, ok = m["not"]
fmt.Println("not exists?", ok)
Then, go run maps.go
somestring exists? true
not exists? false
It is mentioned under "Index expressions".
An index expression on a map a of type map[K]V used in an assignment
or initialization of the special form
v, ok = a[x]
v, ok := a[x]
var v, ok = a[x]
yields an additional untyped boolean value. The value of ok is true if
the key x is present in the map, and false otherwise.
A two value assignment can be used for this purpose. Please check my sample program below
package main
import (
"fmt"
)
func main() {
//creating a map with 3 key-value pairs
sampleMap := map[string]int{"key1": 100, "key2": 500, "key3": 999}
//A two value assignment can be used to check existence of a key.
value, isKeyPresent := sampleMap["key2"]
//isKeyPresent will be true if key present in sampleMap
if isKeyPresent {
//key exist
fmt.Println("key present, value = ", value)
} else {
//key does not exist
fmt.Println("key does not exist")
}
}
Example usage: Looping through a slice, for pairMap checking if key exists.
It an algorithm to find all pairs that adds to a specific sum.
func findPairs(slice1 []int, sum int) {
pairMap := make(map[int]int)
for i, v := range slice1 {
if valuei, ok := pairMap[v]; ok {
fmt.Println("Pair Found", i, valuei)
} else {
pairMap[sum-v] = i
}
}
}

Are there any go libraries that provide associative array capability?

I'm looking for a go language capability similar to the "dictionary" in python to facilitate the conversion of some python code.
EDIT: Maps worked quite well for this de-dupe application. I was able to condense 1.3e6 duplicated items down to 2.5e5 unique items using a map with a 16 byte string index in just a few seconds. The map-related code was simple so I've included it below. Worth noting that pre-allocation of map with 1.3e6 elements sped it up by only a few percent:
var m = make(map[string]int, 1300000) // map with initial space for 1.3e6 elements
ct, ok := m[ax_hash]
if ok {
m[ax_hash] = ct + 1
} else {
m[ax_hash] = 1
}
To expand a little on answers already given:
A Go map is a typed hash map data structure. A map's type signature is of the form map[keyType]valueType where keyType and valueType are the types of the keys and values respectively.
To initialize a map, you must use the make function:
m := make(map[string]int)
An uninitialized map is equal to nil, and if read from or written a panic will occur at runtime.
The syntax for storing values is much the same as doing so with arrays or slices:
m["Alice"] = 21
m["Bob"] = 17
Similarly, retrieving values from a map is done like so:
a := m["Alice"]
b := m["Bob"]
You can use the range keyword to iterate over a map with a for loop:
for k, v := range m {
fmt.Println(k, v)
}
This code will print:
Alice 21
Bob 17
Retrieving a value for a key that is not in the map will return the value type's zero value:
c := m["Charlie"]
// c == 0
By reading multiple values from a map, you can test for a key's presence. The second value will be a boolean indicating the key's presence:
a, ok := m["Alice"]
// a == 21, ok == true
c, ok := m["Charlie"]
// c == 0, ok == false
To remove a key/value entry from a map, you flip it around and assign false as the second value:
m["Bob"] = 0, false
b, ok := m["Bob"]
// b == 0, ok == false
You can store arbitrary types in a map by using the empty interface type interface{}:
n := make(map[string]interface{})
n["One"] = 1
n["Two"] = "Two"
The only proviso is that when retrieving those values you must perform a type assertion to use them in their original form:
a := n["One"].(int)
b := n["Two"].(string)
You can use a type switch to determine the types of the values you're pulling out, and deal with them appropriately:
for k, v := range n {
switch u := v.(type) {
case int:
fmt.Printf("Key %q is an int with the value %v.\n", k, u)
case string:
fmt.Printf("Key %q is a string with the value %q.\n", k, u)
}
}
Inside each of those case blocks, u will be of the type specified in the case statement; no explicit type assertion is necessary.
This code will print:
Key "One" is an int with the value 1.
Key "Two" is a string with the value "Two".
The key can be of any type for which the equality operator is defined, such as integers, floats, strings, and pointers. Interface types can also be used, as long as the underlying type supports equality. (Structs, arrays and slices cannot be used as map keys, because equality is not defined on those types.)
For example, the map o can take keys of any of the above types:
o := make(map[interface{}]int)
o[1] = 1
o["Two"] = 2
And that's maps in a nutshell.
The map type. http://golang.org/doc/effective_go.html#maps
There is some difference from python in that the keys have to be typed, so you can't mix numeric and string keys (for some reason I forgot you can), but they're pretty easy to use.
dict := make(map[string]string)
dict["user"] = "so_user"
dict["pass"] = "l33t_pass1"
You're probably looking for a map.

Resources