This question already has answers here:
Multiple values in single-value context
(6 answers)
Closed 6 years ago.
In Go I can use the underscore to ignore a return value from a function that returns multiple values. For instance:
res, _ := strconv.Atoi("64")
Suppose I wanted to use the first value directly into another function call (while ignoring error checking best practices, in this example):
myArray := make([]int, strconv.Atoi("64"))
The compiler will complain that I'm using a multiple-value function in a singe-value context:
./array-test.go:11: multiple-value strconv.Atoi() in single-value context
Is it possible to "pick and choose" from the return values in a single-line without resorting to auxiliary functions?
The only real way to do it is to create some utility "bypass" function, and since this is Go, you'll have to declare one per type.
for example:
func noerrInt(i int, e err) int {
return i
}
then you can do:
myArray := make([]int, noerrInt(strconv.Atoi("64")))
But really, this pretty much sucks, AND ignores best practices.
Related
This question already has answers here:
slice of struct != slice of interface it implements?
(6 answers)
Closed 10 months ago.
Prototype function
func test(i ...interface{}) {
// Code here
}
Intended use
type foo struct {
// Fields
}
foos := []foo{
// foo1, foo2 ...
}
test(foos...) // ERROR
test(foos[1], foos[2], ...) // OK
Error
cannot use foos (variable of type []foos) as []interface{} value in argument to test
Description
The intended use is to be used like the built-in function append().
https://golang.google.cn/pkg/builtin/#append
func append(slice []Type, elems ...Type) []Type
Although, as I've seen append() doesn't use interface{}, which is strange, since anywhere that I searched all people say to use interface{} when you don't know the type. But they don't.
Nope, append() uses a "build-in" type called Type, which apparently the docs say that it's a int. Although, I cannot use it. There isn't such type. And neither I would know how to use it if there was.
https://golang.google.cn/pkg/builtin/#Type
type Type int
So, I'm very confused here.
Questions
Why does the spread operator not work as intended? For example, in Javascript the spread operator just spreads the array into items. But in Golang it seems like it keeps the same array parameter type as it is but gives the compiler later an instruction to spread it. Which is odd.
Are we even able to make similar custom mechanisms like append() at all? Or am I a dummy and I'm using something wrong anyway?
I think that this is the issue that you are running into here.
https://github.com/golang/go/wiki/InterfaceSlice
I am not an expert in this but have hit this before, the "slice of empty interface" is not an interface and therefore cannot be replaced by any type which is the issue that you are having, it has to do with the memory structure being different. The above has a far better explanation than one that I can give.
You can typecast your typed slice to get what you need:
generic := make([]interface{}, 0)
for _, f := range foos {
generic = append(generic, f)
}
test(generic...) // works
Combining the two non-negative answers into what I feel is the best solution:
interfaceSlice := make([]interface{}, len(foos))
for i, v := range foos {
interfaceSlice[i] = v
}
test(interfaceSlice...)
Partially inspired by:
https://github.com/golang/go/wiki/InterfaceSlice#what-can-i-do-instead
This question already has answers here:
What does "..." mean when next to a parameter in a go function declaration?
(3 answers)
Closed 3 years ago.
I am referring to following method that takes last argument as args ...interfact{})
func (*sqlx.DB).Select(dest interface{}, query string, args ...interface{}) error
https://godoc.org/github.com/jmoiron/sqlx#DB.Select
From my understanding that the method accepts last parameter of any type which is variadic ..
So
selectStmt = 'Select * FROM users where user_id IN (?)'
selectStmt, userArgs, err := sqlx.In(selectStmt, userIDs)// userIDs is a slice
if err != nil {
return nil, errors.Wrap(err, "")
}
selectStmt = s.db.Rebind(selectStmt)
var users []User
err = s.db.Select(&users, selectStmt, userArgs) // wrong one .. Line A
err = s.db.Select(&users, selectStmt, userArgs... ) // right one .. Line B
In the aforementioned code if i comment out Line B , but not Line A it doesn't work. I get following error.
sql: converting argument $1 type: unsupported type []interface {}, a slice of interface *
Question
What exactly happening here , why can't go infer the variadic automatically ?? What is the need of passing extra '...' to the third argument?
What exactly happening here , why can't go infer the variadic automatically ?? What is the need of passing extra '...' to the third argument?
Go doesn't infer the variadic automatically - in fact, Go intentionally infers very little and does very little automatically. You need the ... because it does not infer. It also makes clear, when you pass a slice to a variadic, whether you mean for it to be exploded, or you mean for the slice itself to be a single argument; either could be a valid use case, and rather than making assumptions, Go expects you to be explicit.
This question already has answers here:
Multiple values in single-value context
(6 answers)
Closed 6 years ago.
I'm trying to initialize a struct in Go, one of my values is being which returns both an int and an error if one was encountered converted from a string using strconv.Atoi("val").
My question is : Is there a way to ignore an error return value in Golang?
ts := &student{
name: td[0],
ssn: td[2],
next: students.next,
age: strconv.Atoi(td[1]),
}
which gives the error
multiple-value strconv.Atoi() in single-value context
if I add in the err, which i don't want to include in my struct, I will get an error that I am using a method that is not defined in the struct.
You can ignore a return value using _ on the left hand side of assignment however, I don't think there is any way to do it while using the 'composite literal' initialization style you have in your example.
IE I can do returnValue1, _ := SomeFuncThatReturnsAresultAndAnError() but if you tried that in your example like;
ts := &student{
name: td[0],
ssn: td[2],
next: students.next,
age, _: strconv.Atoi(td[1]),
}
It will also generate a compiler error.
This question already has answers here:
What is this "err.(*exec.ExitError)" thing in Go code? [duplicate]
(2 answers)
Closed 7 years ago.
I am reading this code and I don't quite understand what line #2 does:
resp := route.Handler(req)
_, nilresponse := resp.(NilResponse)
if !nilresponse {
type NilResponse struct {
}
Thank you
This isn't an empty function name. This is a type-assertion. It is testing that resp is a NilResponse. If it is, then nilResponse will be true, otherwise it will be false. This code throws away the resulting type-asserted value by using _.
See Type Assertions.
If line two is _, nilresponse := resp.(NilResponse) then it's not a function call at all. It's a type assertion. The code is saying "the interface value represented by resp is of type NilResponse.
EDIT; your assignment is kind of odd though because the first return value would be the NilResponse object and the second (if specified) is a flag to indicate whether or not it worked (or maybe an error, can't remember if it's a bool or error). So typically it would be something like; nilResponse, ok := or nilResponse, err :=
This question already has answers here:
Generic variadic argument in Go?
(3 answers)
Closed 8 months ago.
Let's say I want to make the equivalent of the JavaScript Array.splice function in Go, for Slices. I have the following code:
func splice(slice []int, index, amount int, elements ...int) []int {
newslice := make([]int, 0)
for i := 0; i < index; i++ {
newslice = append(newslice, slice[i])
}
for i := index + amount; i < len(slice); i++ {
newslice = append(newslice, slice[i])
}
for _, el := range elements {
newslice = append(newslice, el)
}
return newslice
}
This example will work, but only for arguments of type int. I want to make it generic, and I know that I should give the variadic argument elements the type interface{}, but how do I create a new slice with the type of that interface from inside the function?
In other words, how can I specify the type of the slice dynamically depending on the type of the arguments in the first line of the function, where newslice is created?
Using reflection
If you really want to do generic stuff, reflection is the ultimate answer.
See the MakeSlice documentation
in the reflection package for details on your problem.
You just need to retrieve the type of the incoming slice (using TypeOf(...))
and applying MakeSlice correctly.
Example of using reflection to create a slice:
y := []int{1,2,3}
t := reflect.TypeOf(y)
slice := reflect.MakeSlice(t, 0, 10)
slice = reflect.Append(slice, reflect.ValueOf(2))
fmt.Println(slice.Interface())
Run it here.
Using []interface{}
Another way to work with, is []interface{}, which can store any value
but may lead to runtime panics as you omit compiler type checking completely
(this is a bad thing).
Here is an example for using []interface{}
as storage for arbitrary values. With this you don't need to know the type in
your splice implementation, you just splice and use []interface{} for new slices.
This method has the drawback, that you can't convert some slice to []interface{} easily. You have to copy it manually, as described in posts before.
Conclusion
Regardless of which version you use, you will never get back type safety without
knowing the type and converting it back manually. There's no such thing in Go
which will do that for you. That means, that you'll have something like this
in your code to regain type safety:
x := []int{1,2,3,4}
y := splice(x, ...)
yn := []int(y)
Instead of emulating JavaScript in Go (why ???) I would like to suggest to compose simmilar required operations from the building blocks of SliceTricks.
They are:
Completely type agnostic (think "generics" for free).
Quite probably pretty faster compared to packing/unpacking whatsoever in/from a []interface{}.