How to access individual values from a multi-value returning function? - go

Go functions can return multiple values:
func f() (int, int) {
return 2, 3
}
Is there any way to access individual values from such a multi-value returning function except assignment, i.e. suppose there is
func g(i int) {...}
is there is simpler way to write the following two lines?
_, i = f()
g(i)

My personal favorite would be g(f()[1]) but that's not possible either.
The current solution used by the standard library is to write simple helper functions which are dropping the unwanted return values. For example, take a look at the template package.
A lot of functions there return a (*Template, os.Error) tuple, but there is a helper called template.Must() which only returns a *Template and panics if the error isn't nil.
Alternatively, a general helper function like func extract(index int, values ...interface{}) interface{} might do the trick. But since there isn't support for generics yet, I wouldn't write something like that.

Use an anonymous struct instead of multiple return values.
func f() (struct{i,j int}) {
return struct{i, j int}{2, 3}
}
func g(i int) { ... }
func main() {
g(f().j)
}
Of course this only works when you are writing the function. Though you can wrap existing ones with this if you want.

g(func(fst,snd int) int { return snd }(f()))
or defined snd
func snd(x, y int) int {
return y
}
g(snd(f()))
or if function return array
func f() ([2]int) {
return [2]int{2, 3}
}
g(f()[1])

There isn't a simpler way.
A possible solution would look for example like this:
g(f().1)
There is no syntactic support for a feature like this one in Go.

Related

How to receive multiple values returned by a method in testify framework "assert" method as an argument?

Below is a sample code , which is returning multiple values .
func (c Calc) CreateTenantHandler(item *models.TenantInput) (*models.Response, *models.ErrorDetails) {
...
...
...
return &models.Response{ResponseStatus: 201, TenantOutput: tenantoutput,}, nil
}
In test file I have tried tried doing below things.
assert.Equal(t,[nil,nil],testObject.CreateTenantHandler(nil) );
I also checked other answers but couldn't find what I need.
You don't. It has nothing to do with testify--that's just how Go works. Set multiple variables to the return values, then assert each one individually:
x, y := testObject.CreateTenantHandler(nil)
assertEqual(t, x, expectedX)
assertEqual(t, y, expectedY)
The issue is that you want to convert several return values into a single value that is usable by assert.Equal.
You can do this by passing multiple values to a variadic function that converts all the values (no matter how many) into a single slice of interfaces. That slice is then treated as a single value and works quite well with testify assert.Equal.
The shim function mentioned elsewhere is close, but it has a fixed number of parameters. makeIS() below is less code, cleaner, simpler and works with any number of return values/parameters. Put this function in your test package.
// makeIS will convert any number of parameters to a []interface{}
func makeIS(v ...interface{}) []interface{} {
return v
}
Now the assert work like this
assert.Equal(t, makeIS(eX,eY), makeIS(iReturnTwoValues())
The testify knows how to make the comparison and reports differences in the individual parameters very well. Notice this has the added benefit of "looking like" the call you want to test with the two target values to the left of the function.
One simple way to do the thing you want is to declare a function like shim:
func shim(a, b interface{}) []interface{} {
return []interface{}{a, b}
}
and then:
assert.Equal(t, shim(5,6), shim(testObject.CreateTenantHandler(nil)));
The behavior is described thoroughly in the link below:
source: http://zacg.github.io/blog/2014/10/05/go-asserts-and-multiple-return-values/
you can add convert function to fix it
package multi_return
import (
"github.com/stretchr/testify/assert"
"testing"
)
func multiReturn() (int, float32) {
return 1, 2
}
func toSlice(a ...interface{}) []interface{} {
return a
}
func TestMultiReturn(t *testing.T) {
assert.Equal(t, []interface{}{int(1), float32(2)}, toSlice(multiReturn()))
}

GoLang Implement an anonymous function of a custom type

I have completed the strains exercise on exercism.io. I am refactoring my solution. For context: Ints.Keep takes in a predicate function and returns a filtered slice of type Ints for every element where the predicate function is true. Conversely Discard returns all elements for which the predicate is not true. Discard returns the inverse of Keep. I implemented it like so:
func (i Ints) Keep(pred func(int) bool) (out Ints) {
for _, elt := range i {
if pred(elt) {
out = append(out, elt)
}
}
return
}
func (i Ints) Discard(f func(int) bool) Ints {
return i.Keep(func(n int) bool { return !f(n) })
}
Example usage
Now I am trying to clean it up slightly. I want to create:
type Predicate func(int) bool
Then I want to implement Keep and Discard where the input is a Predicate. I run into the issue when I try to create an anonymous function within Discard to return Keep:
func (i Ints) Discard(p Predicate) Ints {
return i.Keep(Predicate(n int) { return !p(n) })
}
Is this possible? I can't find a way to create an anonymous function of a named func type.
You can do it by casting the anonymous function as a Predicate Like this:
func (i Ints) Discard(p Predicate) Ints {
return i.Keep(Predicate(func(i int) bool { return !p(i) }))
}
This isn't quite as clean as I wanted, but I bet this is the best.
I guess you are misunderstanding text replacement with type subtitution, see:
f func(int) bool gets replaced by p Predicate
func and bool (wrapping (n int)) somehow gets replaced by Predicate.
As far i remember type substitution is very straightforward and that is not the case here... "Mu is too short" highlights a good example if you insist on using type... although it is perfect to use anonymous functions definitions and declarations.
Another way to write code that comes to my mind that you might find useful is:
type Predicate func(int) bool
func (i Ints) Discard(pred Predicate) Ints {
var anonymousComplementFunc Predicate = func(n int) bool {
return !pred(n)
}
return i.Keep(anonymousComplementFunc)
}

Return only the first result of a multiple return values in golang

Absolute newbie question here.
Some functions in Go return more than one value (normally, the value and an error). I was writing a func who return the return value of one of those functions, and even if it is very easy to put the values on variables and return only the first one, I have the doubt if I could do the same in only one line without the extra variable. This is something often uses in other languages like C, Java, C#, Ruby, etc
func someFunc (param string) int {
// do something with the string, not very important
return strconv.Atoi(param)
}
I know this works
func someFunc (param string) int {
// do something with the string, not very important
var result int
result, _ = strconv.Atoi(param)
return result
}
It is this possible in Go? It is considered a "good practice" (like in Java*)
Note: Before someone say that this technique is not a good practice in Java, clarify that is not important for the question, but some people (like the ones in the company I work) encourage that style.
Use a short variable declaration for the shortest code to accomplish this goal:
func SomeFunc(parm string) int {
result, _ := strconv.Atoi(param)
return result
}
There is no one line solution without introducing a helper function that accepts two arguments and returns the first. One of these helper functions would be needed for each combination of types where you want to ignore a value.
Your best possible one-liner is a helper function written as:
func first(n int, _ error) int {
return n
}
func SomeFunc(param string) int {
return first(strconv.Atoi(param))
}
Note that:
the argument types and positions must match exactly
the second argument to first has the blank identifier (_), making it clear that you wish to completely ignore it. [1]
If you absolutely don't want to declare a named function, you may use a function literal, but that looks real ugly:
func SomeFunc(param string) int {
return func(n int, _ error) int { return n }(strconv.Atoi(param))
}
In general, the helper function is worth it if you have a lot of repetition in your code. Otherwise just use a temp variable, which looks clean and idiomatic:
func SomeFunc(param string) int {
n, _ := strconv.Atoi(param)
return n
}
Playground: https://play.golang.org/p/X8EOh_JVDDG
Once generics will be added to the language in Go 1.18, you will be able to write a helper function that can be used with any return pair and preserve type safety on the first one:
func first[T, U any](val T, _ U) T {
return val
}
func SomeFunc(param string) int {
return first(strconv.Atoi(param))
}
Go2 Playground: https://go2goplay.golang.org/p/vLmTuwzrl5o
Footnotes:
[1] Keep in mind that in case of strings.Atoi the second return value is an error, and ignoring errors is bad practice. However there are cases where the success of the operation truly doesn't matter, then it's fine to use _ to ignore the argument.

Is it possible to get return values selectively on single-value contexts in Go?

A simple example:
package main
import "fmt"
func hereTakeTwo() (x, y int) {
x = 0
y = 1
return
}
func gimmeOnePlease(x int){
fmt.Println(x)
}
func main() {
gimmeOnePlease(hereTakeTwo()) // fix me
}
Is it possible to pass only first returned value from hereTakeTwo() without using an explicit _ assignment? Example of what I would like to avoid:
func main() {
okJustOne, _ := hereTakeTwo()
gimmeOnePlease(okJustOne)
}
What I want is to make gimmeOnePlease function able to receive an undefined number of arguments but take only first one OR a way to call hereTakeTwo function and get only first returned value without the necessity to use _ assignments.
Or on a last resort (crazy idea) use some kind of adapter function, that takes N args and reurns only first one, and have something like:
func main() {
gimmeOnePlease(adapter(hereTakeTwo()))
}
Why? I'm just testing the boundaries of the language and learning how flexible it can be to some purposes.
No, you cannot do that apart from one special case described in the Spec:
As a special case, if the return values of a function or method g are equal in number and individually assignable to the parameters of another function or method f, then the call f(g(parameters_of_g)) will invoke f after binding the return values of g to the parameters of f in order. The call of f must contain no parameters other than the call of g, and g must have at least one return value.
The best you can do besides the temporary variables (which are the best option) is this:
func first(a interface{}, _ ...interface{}) interface{} {
return a
}
func main() {
gimmeOnePlease(first(hereTakeTwo()).(int))
}
Playground: http://play.golang.org/p/VXv-tsYjXt
Variadic version: http://play.golang.org/p/ulpdp3Hppj

How to create a literal slice of an alias to a builtin type in Go

I have some golang code that manipulates slices of an interface type (Comparable). To test my code, I want to create some fake data and operate on it. However, I'm having trouble doing this in a way that is not incredibly tedious. The only thing I can think to do is create a new type for testing (in this case an alias of type int) that satisfies the Comparable interface, and then feed my tests literal slices of that type. I envision it looking something like the following:
type Comparable interface {
LT(Comparable) bool
AsFloat() float64
}
type testInt int
func (self testInt) LT(other Comparable) bool {
return float64(self) < other.AsFloat()
}
func (self testInt) AsFloat() float64 {
return float64(self)
}
func TestAFunction(t *testing.T) {
FunctionToTest([]Comparable{7, 4, 2, 1})
....
}
However, with this example, the compiler will complain that type int cannot be used as a Comparable. I understand why this is happening, but I'm not sure how to solve it. First, I don't know how to create a literal of type testInt. Second, I have to write a significant number of these functions. Working with literal ints is far more convenient for my purposes.
Is there a way to work with type aliases of builtin types such that the compiler can correctly infer the correct type of literals with a minimum of code?
Additionally, is there perhaps a better way to accomplish what I am trying to do, i.e., generate hard data that satisfies an interface for use in testing?
func NewWhatevers(a ...int) (r []Whatever) {
r = make([]Whatever, len(a))
for i, v := range a {
r[i] = Whatever(v)
}
return
}
...
myWhatevers := NewWhatevers(7, 4, 2, 1)
There are a number of ways to accomplish this. The problem, as you correctly state, is that the Go compiler cannot automatically convert int to Comparable (since doing so would require finding all possible equivalent types, and figuring out which of those equivalent types satisfy the Comparable interface, and then if there are more than one... you get the idea). Thus, you'll have to do one of two things:
Write an explicit type conversion:
FunctionToTest([]Comparable{ testInt(7), testInt(4), testInt(2), testInt(1) })
However, if you need a lot of literals, this could get really annoying. Thus, you could also:
Write a function to convert []int to []Comparable:
func intToComparable(i []int) []Comparable {
c := make([]Comparable, len(i))
for i, v := range i {
c[i] = testInt(v)
}
return c
}
and then you'd only have to do:
FunctionToTest(intToComparable([]int{ 7, 4, 2, 1 }))
Additionally, is there perhaps a better way to accomplish what I am trying to do, i.e., generate hard data that satisfies an interface for use in testing?
Maybe. The problem you encountered is that []Comparable and []testInt are fundamentally different and cannot be exchanged as the underlying representation in memory is different.
If your code is less about individual item which are Comparable but more about slices of items which can be compared than you could refactor your code to work on whole Slices.
Have a look at how package sort does this: It doesn't operate on a slice of comparables but on a "comparable slice".
// FloatOrder is a slice with comparable and float-convertible elements
type FloatOrder interface {
Less(i, j int) bool // Compare element i and j and return true first is less than the other
Float(i int) float64 // Return element i as a float64
}
type testInts []int
func (n testInts) Less(i, j int) bool {return n[i] < n[j]}
func (n testInts) Float(i int) float64 { return float64(n[i]) }
func FunctionTotest(fo FloatOrder) { ... }
func TestAFunction(t *testing.T) {
FunctionToTest(testInts{1,2,3,4})
....
}
(Completely untested, illustration-only code)

Resources