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

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.

Related

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

Unable to update Kotlin method parameter's value [duplicate]

This question already has answers here:
Kotlin function parameter: Val cannot be reassigned
(4 answers)
Closed 5 years ago.
I've following Kotlin method
fun getpower(base:Int,power:Int):Int
{
var result = 1
while(power > 0){
result = result * base
power-- // <---- error in this line
}
return result
}
Kotlin compiler gives following error
Error:(6, 8) Val cannot be reassigned
What's wrong with updating the variable?
What's wrong with updating the variable?
The others answer the question by effectively saying "because Kotlin function parameters are immutable." Of course, that is a(the) correct answer.
But given the fact so many languages, including Java, allow you to re-assign function parameters, it might be valid to interpret your question as "why does Kotlin disallow re-assigning function parameters?"
My Answer: Kotlin and Swift have many features in common, so I went to Swift 3 to see why they decided to deprecate function parameter re-assignment and found this motivation.
Using var annotations on function parameters have limited utility, optimizing for a line of code at the cost of confusion with inout , which has the semantics most people expect. To emphasize the fact these values are unique copies and don't have the write-back semantics of inout , we should not allow var here.
In summary, the problems that motivate this change are:
• var is often confused with inout in function parameters.
• var is often confused to make value types have reference semantics.
•Function parameters are not refutable patterns like in if-, while-, guard-, for-in-, and case statements.
Of course, Kotlin has no inout decoration. But the writers could have chosen to allow val and var, with val being the default. Then they would have had behavior consistent with many other languages. Instead, they opted for code clarity.
The OPs example code shows a valid example of when parameter re-assignment is clear and natural. Having to add one more line to a very short function (to get a local variable to do what the parameter variable could have done) IMHO reduces clarity. Again, IMHO, I would have preferred optionally being able to declare my parameters as var.
A function's parameters inside the function are read-only (like variables created with val), therefore they cannot be reassigned.
You can see discussions about this design decision here and here.
In Kotlin, method parameter's are val(non-mutable) type not var(mutable) type. Similar as java final.
That's why i cant mutate(change) that .
The error you saw has more to do with scoping. A function's parameter by design is immutable or more accurately, read-only and that is what the val keyword stands for that is why you see that error.

Changing behavior based on number of return arguments like type assertions

I've been learning Go and one thing that stood out as particularly interesting to me is the way that the behavior of type assertions changes based on how many return values are being captured:
var i interface{} = "hello"
val, ok := i.(int) // All good
fmt.Println(val, ok)
val = i.(int) // Panics
fmt.Println(val)
This feels like a pattern that can be very useful for user defined functions. The user either has to explicitly get the "ok" second return value or use an underscore to ignore it. In either case, they're making it clear that they're aware that the function can fail. Whereas if they just get one return value, it could silently fail. Hence, it seems reasonable to panic or similar if the user isn't checking for an error (which would be reasonable if the error should "never" happen). I assume that's the logic behind the language developers in making type assertions work this way.
But when I tried to find out how that could be done, I found nothing. I'm aware that type assertions aren't an actual function. And many languages with multiple return values can't check how many return values are actually being used (MATLAB is the only one I'm aware of), but then again, most of those don't use behavior like the type assertions demonstrate.
So, is it possible and if so, how? If not, is there a particular reason that this behavior was excluded despite it being possible with the built in type assertions?
Sadly they cannot be used in normal functions. As far as i know only type assertions, map value access and range allow it.
Usually when you want to have a function with one and optional a second error argument you name them like
func DoSomething() (string, error) {...} // i will return an error
func MustDoSomething() string {...} // i will panic
An example would be https://golang.org/pkg/regexp/#MustCompile
This answer: https://stackoverflow.com/a/41816171/10278 by #christian provides the best practical advice for how to emulate the "overloaded-on-result-count" pattern.
My aim is to address another part of the question—this part: "But when I tried to find out how that could be done, I found nothing".
The following explains how it is done for Go type assertions.
Invocations of type assertions in Go behave as though they are overloaded based on number of results.
Yet, Go does not support overloading of methods and operators.
Looking at Go's implementation, here is the reason type assertions appear to be overloaded based on number of results:
The Go compiler provides special handling that is peculiar to these built-in operations.
This special dispatching occurs for the built-in concept of type assertions because the compiler is carving out special logic that is not available to non-built-in code.
The Go compiler and runtime are written in Go. That made it (somewhat) easy for me to discover that the compiler is the key to explaining this behavior.
Take a look at this part of the compiler:
https://github.com/golang/go/blob/8d86ef2/src/cmd/compile/internal/gc/ssa.go#L4782
The code comment already reveals a lot:
// dottype generates SSA for a type assertion node.
// commaok indicates whether to panic or return a bool.
// If commaok is false, resok will be nil.
We can go further by using a debugger to step through some type assertion code.
Take this playground snippet for example. Specifically, these lines:
object_as_closer_hardstop := thing.(io.Closer) // will panic!!
object_as_closer, ok := thing.(io.Closer)
(If you build Go from source, then) if you use a debugger to step into the first type assertion, you will end up at the following code in the Go runtime:
https://github.com/golang/go/blob/8d86ef2/src/runtime/iface.go#L438
If you step into the second one, you end up at:
https://github.com/golang/go/blob/8d86ef2/src/runtime/iface.go#L454
On line 438, you see func assertI2I (with a single return value). A bit lower, on line 454, you see assertI2I2. Note that these two functions have nearly identical names, but not quite!
The second function has a trailing 2 at the end of its name. That function also has two returned results.
As we expect:
assertI2I can panic, but
assertI2I2 cannot.
(Look at the function bodies in iface.go and note which contains panic.)
assertI2I and assertI2I2 abide by the overloading rules we expect. If they were to differ only by number of results, then those of us who compile Go from source would be unable to compile the Go runtime, due to a compiler error such as "assertI2I redeclared".
Users of the language are generally not aware of these builtin runtime functions, so on the surface, both lines of code seem to call the same function:
object_as_closer_hardstop := thing.(io.Closer) // will panic!!
object_as_closer, ok := thing.(io.Closer)
However, at compile time the compiler branches based on whether it found the case "commaok":
https://github.com/golang/go/blob/8d86ef2/src/cmd/compile/internal/gc/ssa.go#L4871
Our own end-user code does not get to modify Go's lexing/parsing/AST-walking in order to dispatch different flavors of our functions based on "commaok".
For better or for worse, that is why user-written code cannot leverage this pattern.

Assign multi-value to struct literal [duplicate]

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.

What are common "Go-tchas" that someone learning Golang should watch out for? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
For example, the "Effective Go" documentation has the following entries:
Like C, Go's formal grammar uses semicolons to terminate statements, but unlike in C, those semicolons do not appear in the source. Instead the lexer uses a simple rule to insert semicolons automatically as it scans, so the input text is mostly free of them.
Cut off some parts for brevity.
Write them like this
if i < f() {
g()
}
not like this
if i < f() // wrong!
{ // wrong!
g()
}
The wrong version when executed produces the following error messages:
/tmp/test.go:6: missing condition in if statement
/tmp/test.go:6: true evaluated but not used
IMO, both messages don't give the coder a clue about misplaced curly braces. Had I failed to read the documentation above, I would have probably written some Go code in the future using the wrong version (I usually use the 1st version in writing code that uses curly braces), then banged my head as to why I'm missing an "if" condition when one is clearly present.
Are there other "gotchas" in Golang that I should be aware of?
This could've been just a comment, but posted as an answer to lay more emphasis on it, because I do believe the linked article is really good, useful even for non-starters and it is still unknown.
This is the best and most complete I've seen:
50 Shades of Go: Traps, Gotchas, and Common Mistakes for New Golang Devs
It has topics ranging from total beginner (like "Opening Brace Can't Be Placed on a Separate Line" or "Unused Imports") to advanced beginner (like "nil" Interfaces and "nil" Interfaces Values or "Preemptive Scheduling").
So a nice summary of the common pitfalls or "gotchas" is basically their table of contents, all of which you can read more about there:
Total Beginner:
Opening Brace Can't Be Placed on a Separate Line
Unused Variables
Unused Imports
Short Variable Declarations Can Be Used Only Inside Functions
Redeclaring Variables Using Short Variable Declarations
Accidental Variable Shadowing
Can't Use "nil" to Initialize a Variable Without an Explicit Type
Using "nil" Slices and Maps
Map Capacity
Strings Can't Be "nil"
Array Function Arguments
Unexpected Values in Slice and Array "range" Clauses
Slices and Arrays Are One-Dimensional
Accessing Non-Existing Map Keys
Strings Are Immutable
Conversions Between Strings and Byte Slices
Strings and Index Operator
Strings Are Not Always UTF8 Text
String Length
Missing Comma In Multi-Line Slice/Array/Map Literals
log.Fatal and log.Panic Do More Than Log
Built-in Data Structure Operations Are Not Synchronized
Iteration Values For Strings in "range" Clauses
Iterating Through a Map Using a "for range" Clause
Fallthrough Behavior in "switch" Statements
Increments and Decrements
Bitwise NOT Operator
Operator Precedence Differences
Unexported Structure Fields Are Not Encoded
App Exits With Active Goroutines
Sending to an Unbuffered Channel Returns As Soon As the Target Receiver Is Ready
Sending to an Closed Channel Causes a Panic
Using "nil" Channels
Methods with Value Receivers Can't Change the Original Value
Intermediate Beginner:
Closing HTTP Response Body
Closing HTTP Connections
Unmarshalling JSON Numbers into Interface Values
Comparing Structs, Arrays, Slices, and Maps
Recovering From a Panic
Updating and Referencing Item Values in Slice, Array, and Map "for range" Clauses
"Hidden" Data in Slices
Slice Data Corruption
"Stale" Slices
Type Declarations and Methods
Breaking Out of "for switch" and "for select" Code Blocks
Iteration Variables and Closures in "for" Statements
Deferred Function Call Argument Evaluation
Deferred Function Call Execution
Failed Type Assertions
Blocked Goroutines and Resource Leaks
Advanced Beginner:
Using Pointer Receiver Methods On Value Instances
Updating Map Value Fields
"nil" Interfaces and "nil" Interfaces Values
Stack and Heap Variables
GOMAXPROCS, Concurrency, and Parallelism
Read and Write Operation Reordering
Preemptive Scheduling

Resources