Golang var and literal usage [duplicate] - go

This question already has answers here:
nil slices vs non-nil slices vs empty slices in Go language
(3 answers)
Closed 11 months ago.
Option 1
var employees []Employee
session.Employees = employees
Option 2
session.Employees = []Employee{}
What, if any, is the difference in the two Golang code options, with respect to session.Employees after execution?

Your first version assigns the value of the employees variable to session.Employees. It will be the zero value of the type []Employee, which is nil. You could simply write this as:
session.Employees = nil
Your second version assigns the value of a composite literal, which will be an empty (length=0, capacity=0) but non-nil slice.
See related questions:
nil slices vs non-nil slices vs empty slices in Go language
What is the point of having nil slice and empty slice in golang?
Correct way to initialize empty slice

Related

What happens when I range over an uninitialized pointer to array in golang

I have this code
var j *[33]byte
for i := range j {
fmt.Println(j[i])
}
Now when I run this code I get nil pointer dereference error when I try access values in j. I'm not sure why I was even able to enter the loop in the first place considering my pointer is uninitialized.
I know an uninitialized array has all its values set to their zero value. That is
var a [5]int
Will have a default value of [0, 0, 0, 0, 0].
But I don't understand what golang does when you don't initialize a pointer to an array. Why is range able to range over it even though its nil?
From the Go spec Range Clause:
... For an array, pointer to array, or slice value a, the index
iteration values are produced in increasing order...
so as a convenience the Go language is dereferencing the pointer with the intent to iterating over its elements. The fact that the pointer is nil is a simple programming error. If this can occur, one should have a runtime check in place to guard against it.
Static analysis may be able to detect this type of bug ahead of time - but what if the variable j is accessible from another goroutine - how would the compiler know for sure that another goroutine may update it to a non-nil value right before the range loop is reached?
Go has a zero value defined for each type when you initialize a variable with var keyword (this may change when using :=, ideally used when need copies of values or specific values). In the case of the pointer the zero value is nil (also maps, interfaces, channels, slices, and functions) in case of array of type int the zero value is 0.
So, to answer your question, Go is able to iterate because you have 33 valid spaces idependently of what value is inside of that position. You can check the diference between slices and arrays on the Golang documentation to have more insights on why is that.

What is {} in Golang? [duplicate]

This question already has an answer here:
Anonymous struct, difference between struct{}{} and {}
(1 answer)
Closed 10 months ago.
I came across this in lecture notes:
setCollection := map[string]struct{}{
"uniqElement1": {},
"uniqElement2": {},
"uniqElement3": {},
}
As I understand, {} here represents the empty struct, but I never saw this before. Does this always mean an empty struct? Also, when can we use this notation? This code doesn't work:
setCollection["newElem"] = {}
{ and } are syntax requirement of composite literal values.
Your first example uses a composite literal to create a map value, and inside that literal it uses other struct literals for the key values of the map. And the Spec allows to omit the inner type in the inner literal:
Within a composite literal of array, slice, or map type T, elements or map keys that are themselves composite literals may elide the respective literal type if it is identical to the element or key type of T. Similarly, elements or keys that are addresses of composite literals may elide the &T when the element or key type is *T.
Your second example tries to use {} not in a composite literal, and the compiler does not know what type you want to use. So it's a compile time error. You have to be explicit in the second example:
setCollection["newElem"] = struct{}{}
Where struct{} is the type, and struct{}{} is a composite literal value (of type struct{}).
See related: How do struct{} and struct{}{} work in Go?

Better way to deal with nil slice indexes

I have started a project for creating reports by utilizing excel data and the various Go excel libraries (excelize, tealeg's xlsx)
One of the biggest frustrations I have found is working with slices which have some nil indexes depending on the source of data (blank rows in the input data transfer as "nil" slice indexes when I use the xlsx library to pull data)
These nil slice index throw an "index out of range" obviously if I ever try and utilize them in one of my many for loops - which leads me to the painstaking task of ensuring each time I want to work with a slice index that is isn't actually nil by using len() and cap to death()(excerpt of code below to illustrate)
//example code excerpt
for rowNumber, cellStringSlice := range inputSlice {
for rowColumn, cellString := range cellStringSlice {
//loop var declaration
rowColumnHeading := 2
rowNumberInc := rowNumber + 1
rowNumberDec := rowNumber - 1
if rowNumber > 0 {
if len(inputSlice[rowNumber]) != 0 { //len check to stop index out of range issue with slice
previousColACellValue = inputSlice[rowNumber][rowColumn]
continue
}
if len(inputSlice[rowNumber+1]) != 0 { //len check to stop index out of range issue with slice
nextColACellValue = inputSlice[rowNumber+1][rowColumn]
continue
}
}
}
I should specify that in this 2D slice I am using:
inputSlice[rowNumber][rowColumn]
the proximal slice (rowNumber) is never nil (there is always a row) however the second distal slice it indexes (rowColumn) Can be nil on some instances - which is why in this scenario my overall loop always enters the second inner loop even when it is iterating though a row with no column data (i.e inputSlice[rowNumber][rowColumn] = nil) and brings a frequent need for me to handle index out of range issues
I can't just remove all the nil indexes and shift everything up, as these are representing "blank rows" in the final excel doc I output these rows to.
So my question is, are there any useful go functions or libraries which take care of nil indexes by swapping all nils for "" in slices and 2d/3d slices of type string? Or is it a task for the programmer to always "sanitise" his slices by removing these nils or check for them each time they ever want to access an element?
I appreciate I could write a for loop myself to swap all these nils for a "", but writing a function to do this each time I work with slices of strings containing/possibly containing nil's would seem a little bizarre to me
Your outer loop is on inputSlice, so inputSlice[rowNumber] is always valid, and since the inner loop is on that row, it is never zero. Thus the first check is unnecessary. If you have a nil or empty slice for inputSlice[rowNumber], the inner for loop will not even be entered.
The second check is necessary, but wrong:
if len(inputSlice[rowNumber+1]) != 0 {
If rowNumber is the last row, then inputSlice[rowNumber+1] is not valid as no such row exists. You have to check:
if rowNumber<len(inputSlice) {
...
}

How is mapping done internally in golang? [duplicate]

This question already has answers here:
Meaning of underscore (blank identifier) in Go [duplicate]
(5 answers)
Closed 6 years ago.
Here is specific example
func main(){
m := make(map[string]int)
m["k1"] = 7
_, prs := m["k2"]
fmt.Println(prs)
}
What does "_" signifies here?
Rest is clear to me.
The _ means that you don't care about this particular return value.
Accessing a map index yield 2 values :
The value a that index, or the zero-value of the value type
A boolean indicating whether or not a value was at that index
In your case, prs will be the boolean.
This pattern is often used like this :
if _, found := m[key]; !found {
// Do something here to handle the fact that there is nothing at the index `key`
}
Map being a special type in Go, the second value is optional, so if you don't care about whether or not there is something in the map you don't have to check for it.
See dokumentation. Your statement:
_, prs := m["k2"]
is doing two things at the same time. A) Checking whether a key/value is present in the map and B) is retrieves the value. "prs" is a boolean indicating whether the value was present for the key "k2" or not.
Thus, if you only want to check if a key/value is present in the map and do not care to use the value, you can use the "_" to ignore the value and only use the "prs" boolean.

mixing "exploded" slices and regular parameters in variadic functions

I'm wondering why it's not possible to do the following in go:
func main() {
stuff := []string{"baz", "bla"}
foo("bar", stuff...)
}
func foo(s ...string) {
fmt.Println(s)
}
In my understanding, slice... "explodes" the slice so it can be used for multi argument function calls. So the above example should actually expand to foo("bar", "baz", "bla").
foo(stuff...) works as expected, no surprises here, but in the example above, the compiler complains about too many arguments.
Is this a desired limitation? I'm coming from a ruby background where a foo("bar", *stuff) is perfectly fine (and is, at least in my book, the same thing), that's why this surprises me.
The value for a variadic argument can be specified either by enumerating the elements, or using an existing slice, specified by its name followed by ....
You want to mix the 2 possible ways which is not permitted by the Go Language Specification (Passing arguments to ... parameters).
If the first form is used (enumerating the elements):
The value passed [as the variadic parameter] is a new slice of type []T with a new underlying array whose successive elements are the actual arguments.
If the latter is used (passing an existing slice followed by ...) no new slice is created, the one you pass is used as is. And the passed slice can only be used to specify the value of one – the final – variadic parameter. Attempting to pass both a single element and a slice will not match the signature (the parameter list in this case) of your function and you'll get an error:
too many arguments in call to foo
There is no actual "exploding" involved in Go, the term is just used in other languages to help visualize that the passed array or slice will not be an element of the variadic parameter but will be the value of variadic parameter itself.
Mixing the 2 would require to allocate a new slice because obviously the existing slice cannot be used.
The ugly way to get this to work is make it into a new variadic.
foo(append([]string{"bar"}, stuff...)...)
And if the order doesn't matter:
foo(append(stuff, "bar")...)
https://play.golang.org/p/mY6y0vScfPB
The specification on this is at the "Passing arguments to ... parameters":
If f is variadic with a final parameter p of type ...T, then within f the type of p is equivalent to type []T.
If f is invoked with no actual arguments for p, the value passed to p is nil.
Otherwise, the value passed is a new slice of type []T with a new underlying array whose successive elements are the actual arguments, which all must be assignable to T.
In your case, where stuff... works:
If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.
But "bar", stuff... doesn't match either case specified above.
T, []T doesn't match f([]T).
I ran into this situation when preparing arguments to feed to external commands. If possible, just build an one argument slice, then you don't have to worry about combining scalars with slices when it's time to call the function:
package main
import "os/exec"
func main() {
stuff := []string{"bar"}
stuff = append(stuff, "baz", "bla")
exec.Command("name", stuff...).Run()
}

Resources