Assign multi-value to struct literal [duplicate] - go

This question already has answers here:
Multiple values in single-value context
(6 answers)
Closed 7 years ago.
Is there any way in Go to do this:
segment := Segment{
CumulativeDistanceMm: strconv.Atoi(record[9]),
Length: strconv.Atoi(record[1]),
LinkId: strconv.Atoi(record[8]),
SegmentId: strconv.Atoi(record[2]),
}
The error that I get is that strconv.Atoi returns multiple values so I can't assign it directly to the struct properties. If it was a variable I could use the underscore to ignore the second value. Can I do something similar for structs?

strconv.Atoi can fail and you have to deal with this failure. If such failures are absolutely impossible you would write a function func MustAtoi(s string) int which panics on failure and use that one in your struct initialization.
In Go doing some programming instead of using syntactical sugar or fancy syntax is common.
Most probably you should rethink your error handling.

Related

Golang: The differences between these two ways of initializing struct [duplicate]

This question already has answers here:
When to use pointers [duplicate]
(1 answer)
I don't understand when to use pointers on go [duplicate]
(2 answers)
Difference between returning a pointer and a value in initialization methods [duplicate]
(1 answer)
Pointers vs. values in parameters and return values
(5 answers)
Golang struct initialization
(2 answers)
Closed 15 days ago.
I am wondering what the differences are between those two ways of initializing a struct in Go. Does the second one give you a pointer storing the address of the struct? But they have the same syntax if we want to change the field variables, so how are they different?
I can de-reference the pointer, apparently. But do they have different functionalities? In what scenario would I prefer one over the other?
b := Student{Name:"Bob"}
pb := &Student{Name:"Bob", Age:8,}
They only differ in what the type of the local variable is. Whether to prefer one over the other depends entirely on how you would use that variable in the remainder of the function's body. If you are always passing it around (meaning use it on the right-hand side of an assignment, as an argument to a function call, or returning it) as a pointer, use the pb := &Student{...} form. If you intend to create (shallow) copies of it, the b := Student{...} form might be more convenient. This is however purely based on the fact that typing pb is easier than &b, and that typing b is easier than *pb. If you apply these substitutions everywhere (except for in the context of field accesses, where it is allowed but not mandatory, see below), they are completely interchangeable.
If you want to be able to set the variable holding the struct (pointer) to nil, use a pointer, obviously. But this can also be solved by introducing a new, pointer-typed variable and setting that to either nil or &b.
Some types in Go cannot be copied (this is typically accomplished by embedding a [0]sync.Mutex field in the struct, which takes up no space but triggers the "mutex copy" error of the compiler). An example would be protobuf structs. For these, it is almost always preferable to use the pointer form; however, this is not required, as the initialization via b := Student{...} is not a copy.
Go allows transparently dereferencing when accessing struct fields. b.Name, (&b).Name, pb.Name, (*pb).Name all work and are equivalent. Note however that transparent dereferencing only works over one level, (&pb).Name will result in a compiler error.
The composite literals differ in the initialization of the Age field. The first sets the field to the zero value. The second sets the field to the number 8. Otherwise, the initialization of the struct values is identical.
What happens next is where the key difference lies. The first example assigns the value to a variable named b. The second example takes assigns the value to an anonymous variable; takes the address of the variable; and assigns the result to a variable named pb.
The type of b is the struct type and the type of pb is a pointer to the struct type.
See I don't understand when to use pointers on go to see a discussion on why one might want to use a pointer.

What does ` {…}` mean? [duplicate]

This question already has an answer here:
What is the meaning of "...Type" in Go?
(1 answer)
Closed 2 years ago.
In a lot of go repositories in many places generally, when error responses are generated i see
if error != nil {…}
What does {…} mean here.
In this case '{...}' is not really a Golang syntactic construct but just usage of ellipsis to say "here in this {} block you should do something to handle error". It is just placeholder for subjective code to handle error in a way that makes sense in your use case. People do that in documentation to keep examples not-cluttered by error handling logic but still highlighting proper usage of library including error handling.
For completeness there are other places in Golang where ... actually has a special meaning. Those places are:
As argument to go command ... means recursive package list wildcard. go test ./... will test all golang packages found in directory './' and any level of subdirectories
Array literals arr := [...]string{"foo", "bar"} will substitute ... with number of items in array literal, here it will be 2. If you add "baz" at some point, you don't have to update number in [].
Variadic function arguments func foo(args ...int) - see here.
When passing a slice to a variadic function you can unwrap it by adding ... and each element of the slice will be passed as an additional argument. See sum(nums...) in example linked above.

What does a pair of round brackets syntax expression mean in Go? [duplicate]

This question already has answers here:
Typecasting in Golang
(5 answers)
Closed 2 years ago.
Reading this https://github.com/go-pg/pg/wiki/Writing-Queries#select I see many times this expression:
(*Book)(nil)
Example:
count, err := db.Model((*Book)(nil)).Count()
What does it mean?
That is a type conversion. Assuming the db.Model function takes interface{}, it sends an nil interface of type *Book to the function.
To convert a value v to type Book, you'd write:
Book(v)
However, you cannot write Book(nil) because nil is a pointer and Book is not. If you had a type
type BookPtr *Book
Then you could've written BookPtr(nil). Extending that, you want to write *Book(nil), but that means *(Book(nil)) which is invalid, hence:
(*Book)(nil)
'nil' is to Go what NULL/null is to other languages like C#/Java, etc. The *Variable is just getting the pointer value for the Book object of Model.
So in this case, I believe what's happening here is that (*Book)(nil) is setting the pointer value of the Book object of the Model to nil(/null).
Hope this helps in some way. 😊
Good Resource: https://go101.org/article/nil.html

Why can a const initializer not be nil? [duplicate]

This question already has answers here:
Declare a constant array
(5 answers)
Closed 3 years ago.
I have a type A that is basically a simple map:
type A map[int32]struct{}
Now, I would like to have a special value of this type to be able to treat it a bit differently. I thought that it would be smart to use nil for this propose (additionally, this way, all non initialized variables of type A would have this value, and this is also what I would like to have):
const s A = nil
But I got
const initializer cannot be nil
Sure I can accept this and refactor my program in dozens of different ways. But I'm still wondering why it's impossible to initialize const to nil? There must be an architectural reason but I don't see it.
(Note that I prefer to "rename" nil instead of using it directly only because the name nil is not very intuitive in my case.)
I believe that it is because you can only have constants of type boolean, rune, integer, floating-point, complex, and string.
Docs: https://golang.org/ref/spec#Constants
Whereas nil is a zero-value for types pointer, interface, map, slice, channel and function
Docs: https://golang.org/ref/spec#The_zero_value
You can read more here https://blog.golang.org/constants

How can I use the result of a multi-value returning function as the argument of another function in Golang if I don't need error handling? [duplicate]

This question already has answers here:
Multiple values in single-value context
(6 answers)
Closed 4 years ago.
The following is what I want to achieve
fmt.Println(string(ioutil.ReadAll(res.Body)))
But this throws the following error.
multiple-value ioutil.ReadAll() in single-value context
I know that ioutil.ReadAll() returns the bytes and the error. But I don't want to write an extra line as follows
bytes, _ := ioutil.ReadAll(resp.Body)
Is it possible to just pass the result of ioutil.ReadAll() to fmt.Println() if don't care abut error handling in Go?
If you want it only once, it makes little sense in my opinion. However if this is a common situation and you feel that it improves code readability a lot, try something like:
// perhaps, there's a better name for this
func resultToString(b []byte, _ error) string {
return string(b)
}
// and later:
fmt.Println(resultToString(ioutil.ReadAll(res.Body)))
Unfortunately, that's a string-specific function, so for any other type you'll need to duplicate it.

Resources