Any difference between nil check left on right - go

This is function takes two strings and returns struct or nil and I wrote a struct inside this function for use only this function.
type OrgFundingsDetailsFCT struct {
ID int `db:"id"`
OrgProfileID int `db:"org_profile_id"`
OrgID int `db:"org_id"`
RefID string `db:"ref_id"`
AmountUSD float64 `db:"amount_usd"`
FundingDate string `db:"funding_date"`
Status string `db:"status"`
Round string `db:"round"`
CreatedBy string `db:"created_by"`
}
func (s *Server) getCompareOrgFundingsByRefID(refID, status string) (*OrgFundingsDetailsFCT, error) {
type orgFunding struct {
RefID string `db:"ref_id"`
Status string `db:"status"`
}
var orgFundingsDetailsFCT OrgFundingsDetailsFCT
orgfunding := orgFunding{
RefID: refID,
Status: status,
}
const query = `SELECT id,
org_profile_id,
org_id,
ref_id,
amount_usd,
funding_date,
status,round,
created_by
FROM org_fundings
WHERE ref_id=:ref_id AND status=:status`
if err := s.db.NamedGet(&orgFundingsDetailsFCT, query, orgfunding); err == sql.ErrNoRows {
s.logger.Infof("empty rows! getCompareOrgFundingsByRefID #111 %+v", err)
return nil, nil
} else if err != nil {
s.logger.Infof("errors found! getCompareOrgFundingsByRefID#111 %+v", err)
return nil, err
}
return &orgFundingsDetailsFCT, nil
}
Now I'm checking if this function return nil like this
if nil != orgFundingsRefIdPending{
// logic
}
But my question is if I check like that is it same or not?
if orgFundingsRefIdPending != nil{
//logic
}
If nil left side and check with my result is right side OR, my result is left side and check with nil is right side, Is it same? Does that mean the same thing happens if I put ‍‍‍‍‍‍nil on either side? also if I use struct on use only function is it valid thing?

The getCompareOrgFundingsByRefID() function returns a pointer and an error value. To check if the return value (the pointer) is nil, simply compare it to nil, e.g.:
var refID, status string
// Set input params
orgFundingsRefIdPending, err := getCompareOrgFundingsByRefID(refID, status)
if err != nil {
// Handle error
}
if orgFundingsRefIdPending != nil {
// Use orgFundingsRefIdPending
}
The == and != comparison operators can only be executed (their result can only be determined) if both of their operands are evaluated. Moreover, since these comparison operators are reflexive (meaning a == b is true only and only if b == a), the order does not matter. So a == b and b == a are equivalent.
The order matters if the operator would not be reflexive (e.g. < so a < b is not the same as b < a), or it could matter if not all operands would be needed for its result, such as the logical OR (||), because we know that if any of the operands of || is true, the result is true regardless of the other value. And since Go's || operator uses short-circuit evaluation (if the result is known before evaluating all operands, the rest are not evaluated, going from left-to-right), the order does matter in case of ||. E.g. in f() || g() if f() returns true, the g() function will not be called.
Note: Back to yoru case, if the returned pointer is not nil but you want to check if the pointed struct value is the zero value of its type, you may simply compare it to OrgFundingsDetailsFCT{}:
if orgFundingsRefIdPending != nil {
// Use orgFundingsRefIdPending
// Is it the zero value?
if *orgFundingsRefIdPending == (OrgFundingsDetailsFCT{}) {
// It's the zero value
}
}
For details and more options, see How to check for an empty struct?

Related

Return default value for generic type

How do you return nil for a generic type T?
func (list *mylist[T]) pop() T {
if list.first != nil {
data := list.first.data
list.first = list.first.next
return data
}
return nil
}
func (list *mylist[T]) getfirst() T {
if list.first != nil {
return list.first.data
}
return nil
}
I get the following compilation error:
cannot use nil as T value in return statement
You can't return nil for any type. If int is used as the type argument for T for example, returning nil makes no sense. nil is also not a valid value for structs.
What you may do–and what makes sense–is return the zero value for the type argument used for T. For example the zero value is nil for pointers, slices, it's the empty string for string and 0 for integer and floating point numbers.
How to return the zero value? Simply declare a variable of type T, and return it:
func getZero[T any]() T {
var result T
return result
}
Testing it:
i := getZero[int]()
fmt.Printf("%T %v\n", i, i)
s := getZero[string]()
fmt.Printf("%T %q\n", s, s)
p := getZero[image.Point]()
fmt.Printf("%T %v\n", p, p)
f := getZero[*float64]()
fmt.Printf("%T %v\n", f, f)
Which outputs (try it on the Go Playground):
int 0
string ""
image.Point (0,0)
*float64 <nil>
The *new(T) idiom
This has been suggested as the preferred option in golang-nuts. It is probably less readable but easier to find and replace if/when some zero-value builtin gets added to the language.
It also allows one-line assignments.
The new built-in allocates storage for a variable of any type and returns a pointer to it, so dereferencing *new(T) effectively yields the zero value for T. You can use a type parameter as the argument:
func Zero[T any]() T {
return *new(T)
}
In case T is comparable, this comes in handy to check if some variable is a zero value:
func IsZero[T comparable](v T) bool {
return v == *new(T)
}
var of type T
Straightforward and easier to read, though it always requires one line more:
func Zero[T any]() T {
var zero T
return zero
}
Named return types
If you don't want to explicitly declare a variable you can use named returns. Not everyone is fond of this syntax, though this might come in handy when your function body is more complex than this contrived example, or if you need to manipulate the value in a defer statement:
func Zero[T any]() (ret T) {
return
}
func main() {
fmt.Println(Zero[int]()) // 0
fmt.Println(Zero[map[string]int]()) // map[]
fmt.Println(Zero[chan chan uint64]()) // <nil>
}
It's not a chance that the syntax for named returns closely resembles that of var declarations.
Using your example:
func (list *mylist[T]) pop() (data T) {
if list.first != nil {
data = list.first.data
list.first = list.first.next
}
return
}
Return nil for non-nillable types
If you actually want to do this, as stated in your question, you can return *T explicitly.
This can be done when the type param T is constrained to something that excludes pointer types. In that case, you can declare the return type as *T and now you can return nil, which is the zero value of pointer types.
// constraint includes only non-pointer types
func getNilFor[T constraints.Integer]() *T {
return nil
}
func main() {
fmt.Println(reflect.TypeOf(getNilFor[int]())) // *int
fmt.Println(reflect.TypeOf(getNilFor[uint64]())) // *uint64
}
Let me state this again: this works best when T is NOT constrained to anything that admits pointer types, otherwise what you get is a pointer-to-pointer type:
// pay attention to this
func zero[T any]() *T {
return nil
}
func main() {
fmt.Println(reflect.TypeOf(zero[int]())) // *int, good
fmt.Println(reflect.TypeOf(zero[*int]())) // **int, maybe not what you want...
}
You can init a empty variable.
if l == 0 {
var empty T
return empty, errors.New("empty Stack")
}

How do I pass a nil/null parameter to a stored function?

The server receives a GET request which has the territory_id parameter. This parameter can be nil if the user does not need a filter by territory, or may have an integer number if the user wants to get records only for a specific territory.
Code:
func GetDataList (response http.ResponseWriter, request * http.Request) {
params: = GetRequestParams (request.URL.Query ())
normalID, _: = strconv.Atoi (params ["normal_id"])
territoryId, _: = strconv.Atoi (params ["territory_id"])
var listToCheck [] ObjectDataNormal
query = `select * from get_list_for_predict (year: = $1, territory_in: = $2)`
rows, err = db.Queryx (query,
2011,
territoryId)
if rows! = nil {
// code
}
// code
}
func GetRequestParams (values url.Values) map [string] string {
urlValues: = make (map [string] string, len (values))
for k, v: = range values {
urlValues [k] = v [0]
}
return urlValues
}
The stored procedure in postgresql is designed so that if territory_in is ISNULL, then the filter for this parameter does not work, otherwise, if territory_in is equal to 5, for example, records are taken where the value in the territory field is 5.
And how to implement this on the server side?
If I put territory_id = nil in postman, I get:
ERROR: invalid input syntax for integer: "nil"
If null, then:
ERROR: invalid input syntax for integer: "null".
Also territroyID can not be equal nil. How to pass null to a function depending on user request?
In theory I can check in postages function territory_in = 0, instead of IS NULL. Since when converting a string to int(strconv.Atoi (params ["territory_id"])) territory_in it will be set to 0. But I'm wondering how to send a null parameter to a storage function in golang?
I use sqlx and pgx.
If you save territoryId as a *int instead of int, you can pass nil:
func strToIntPtr(s string) *int {
i, err := strconv.Atoi(s)
if err != nil {
return nil
}
return &i
}
territoryId := strToIntPtr(params["territory_id"])
And then territoryId will be nil anytime it's not a valid int. So they can pass nil, null, or any (or anything that's not a number) and you just treat it as null.

How can v == nil return false and reflect.ValueOf(v).IsNil() return true at the same time?

Here's some code:
var v interface{}
v = (*string)(nil)
// Reflect says it is nil
val := reflect.ValueOf(v)
if val.IsNil() {
fmt.Println("val is nil")
} else {
fmt.Println("val is not nil")
}
// This says it is not nil
if v == nil {
fmt.Println("v is nil")
} else {
fmt.Println("v is not nil")
}
https://play.golang.org/p/apyPa4CNZ6
The output is:
val is nil
v is not nil
How is this possible? Is v nil or not?
Also, if you change the first two lines with
v := (*string)(nil)
then the output clearly states that the variable is nil.
Right now in my project I have a function that accepts a argument of type interface{} and I can't reliably check if it is nil with a simple v == nil. I would like to avoid using the reflect package.
From golang.org:
Under the covers, interfaces are implemented as two elements, a type
and a value. The value, called the interface's dynamic value, is an
arbitrary concrete value and the type is that of the value. For the
int value 3, an interface value contains, schematically, (int, 3).
An interface value is nil only if the inner value and type are both
unset, (nil, nil). In particular, a nil interface will always hold a
nil type. If we store a nil pointer of type *int inside an interface
value, the inner type will be *int regardless of the value of the
pointer: (*int, nil). Such an interface value will therefore be
non-nil even when the pointer inside is nil.
You can try fmt.Printf("(%v, %T)\n", v, v). It prints (<nil>, *string).
When you change first two lines to v := (*string)(nil), v is just a pointer, not an interface.

This nil instance of a struct, that satisfies the error interface, is not showing as nil

This should be a gimme for someone. Why do I not get what I expect ("Error is not nil") here?
http://play.golang.org/p/s8CWQxobVL
type Goof struct {}
func (goof *Goof) Error() string {
return fmt.Sprintf("I'm a goof")
}
func TestError(err error) {
if err == nil {
fmt.Println("Error is nil")
} else {
fmt.Println("Error is not nil")
}
}
func main() {
var g *Goof // nil
TestError(g) // expect "Error is nil"
}
This is, it turns out, a Frequently Asked Question about Go, and the short answer is that interface comparisons compare the type and the value, and (*Goof)(nil) and error(nil) have different types.
Since if err != nil is standard, you want a return value that'll work with it. You could declare var err error instead of var g *Goof: err's zero value is conveniently error(nil)
Or, if your func returns an error, return nil will return what you want.
For more background, here's the start of the FAQ's answer:
Under the covers, interfaces are implemented as two elements, a type and a value. The value, called the interface's dynamic value, is an arbitrary concrete value and the type is that of the value. For the int value 3, an interface value contains, schematically, (int, 3).
An interface value is nil only if the inner value and type are both unset, (nil, nil). In particular, a nil interface will always hold a nil type. If we store a pointer of type *int inside an interface value, the inner type will be *int regardless of the value of the pointer: (*int, nil). Such an interface value will therefore be non-nil even when the pointer inside is nil.
And == is strictly checking if the types are identical, not if a type (*Goof) implements an interface (error). Check out the original for more.
If it helps clarify, this doesn't only happen with nil: in this example, the data underlying the x and y variables is obviously 3, but they have different types. When you put x and y into interface{}s, they compare as unequal:
package main
import "fmt"
type Bob int
func main() {
var x int = 3
var y Bob = 3
var ix, iy interface{} = x, y
fmt.Println(ix == iy)
}

How to do one-liner if else statement? [duplicate]

This question already has answers here:
What is the idiomatic Go equivalent of C's ternary operator?
(14 answers)
Closed 1 year ago.
Please see https://golangdocs.com/ternary-operator-in-golang as pointed by #accdias (see comments)
Can I write a simple if-else statement with variable assignment in go (golang) as I would do in php? For example:
$var = ( $a > $b )? $a: $b;
Currently I have to use the following:
var c int
if a > b {
c = a
} else {
c = b
}
Sorry I cannot remember the name if this control statement and I couldn't find the info in-site or through google search. :/
As the comments mentioned, Go doesn't support ternary one liners. The shortest form I can think of is this:
var c int
if c = b; a > b {
c = a
}
But please don't do that, it's not worth it and will only confuse people who read your code.
As the others mentioned, Go does not support ternary one-liners. However, I wrote a utility function that could help you achieve what you want.
// IfThenElse evaluates a condition, if true returns the first parameter otherwise the second
func IfThenElse(condition bool, a interface{}, b interface{}) interface{} {
if condition {
return a
}
return b
}
Here are some test cases to show how you can use it
func TestIfThenElse(t *testing.T) {
assert.Equal(t, IfThenElse(1 == 1, "Yes", false), "Yes")
assert.Equal(t, IfThenElse(1 != 1, nil, 1), 1)
assert.Equal(t, IfThenElse(1 < 2, nil, "No"), nil)
}
For fun, I wrote more useful utility functions such as:
IfThen(1 == 1, "Yes") // "Yes"
IfThen(1 != 1, "Woo") // nil
IfThen(1 < 2, "Less") // "Less"
IfThenElse(1 == 1, "Yes", false) // "Yes"
IfThenElse(1 != 1, nil, 1) // 1
IfThenElse(1 < 2, nil, "No") // nil
DefaultIfNil(nil, nil) // nil
DefaultIfNil(nil, "") // ""
DefaultIfNil("A", "B") // "A"
DefaultIfNil(true, "B") // true
DefaultIfNil(1, false) // 1
FirstNonNil(nil, nil) // nil
FirstNonNil(nil, "") // ""
FirstNonNil("A", "B") // "A"
FirstNonNil(true, "B") // true
FirstNonNil(1, false) // 1
FirstNonNil(nil, nil, nil, 10) // 10
FirstNonNil(nil, nil, nil, nil, nil) // nil
FirstNonNil() // nil
If you would like to use any of these, you can find them here https://github.com/shomali11/util
I often use the following:
c := b
if a > b {
c = a
}
basically the same as #Not_a_Golfer's but using type inference.
Thanks for pointing toward the correct answer.
I have just checked the Golang FAQ (duh) and it clearly states, this is not available in the language:
Does Go have the ?: operator?
There is no ternary form in Go. You may use the following to achieve the same result:
if expr {
n = trueVal
} else {
n = falseVal
}
additional info found that might be of interest on the subject:
Rosetta Code for Conditional Structures in Go
Ternary Operator in Go experiment from this guy
One possible way to do this in just one line by using a map, simple I am checking whether a > b if it is true I am assigning c to a otherwise b
c := map[bool]int{true: a, false: b}[a > b]
However, this looks amazing but in some cases it might NOT be the perfect solution because of evaluation order. For example, if I am checking whether an object is not nil get some property out of it, look at the following code snippet which will panic in case of myObj equals nil
type MyStruct struct {
field1 string
field2 string
}
var myObj *MyStruct
myObj = nil
myField := map[bool]string{true: myObj.field1, false: "empty!"}[myObj != nil}
Because map will be created and built first before evaluating the condition so in case of myObj = nil this will simply panic.
Not to forget to mention that you can still do the conditions in just one simple line, check the following:
var c int
...
if a > b { c = a } else { c = b}
A very similar construction is available in the language
**if <statement>; <evaluation> {
[statements ...]
} else {
[statements ...]
}*
*
i.e.
if path,err := os.Executable(); err != nil {
log.Println(err)
} else {
log.Println(path)
}
Use lambda function instead of ternary operator
Example 1
to give the max int
package main
func main() {
println( func(a,b int) int {if a>b {return a} else {return b} }(1,2) )
}
Example 2
Suppose you have this must(err error) function to handle errors and you want to use it when a condition isn't fulfilled.
(enjoy at https://play.golang.com/p/COXyo0qIslP)
package main
import (
"errors"
"log"
"os"
)
// must is a little helper to handle errors. If passed error != nil, it simply panics.
func must(err error) {
if err != nil {
log.Println(err)
panic(err)
}
}
func main() {
tmpDir := os.TempDir()
// Make sure os.TempDir didn't return empty string
// reusing my favourite `must` helper
// Isn't that kinda creepy now though?
must(func() error {
var err error
if len(tmpDir) > 0 {
err = nil
} else {
err = errors.New("os.TempDir is empty")
}
return err
}()) // Don't forget that empty parentheses to invoke the lambda.
println("We happy with", tmpDir)
}
Sometimes, I try to use anonymous function to achieve defining and assigning happen at the same line. like below:
a, b = 4, 8
c := func() int {
if a >b {
return a
}
return b
} ()
https://play.golang.org/p/rMjqytMYeQ0
Like user2680100 said, in Golang you can have the structure:
if <statement>; <evaluation> {
[statements ...]
} else {
[statements ...]
}
This is useful to shortcut some expressions that need error checking, or another kind of boolean checking, like:
var number int64
if v := os.Getenv("NUMBER"); v != "" {
if number, err = strconv.ParseInt(v, 10, 64); err != nil {
os.Exit(42)
}
} else {
os.Exit(1)
}
With this you can achieve something like (in C):
Sprite *buffer = get_sprite("foo.png");
Sprite *foo_sprite = (buffer != 0) ? buffer : donut_sprite
But is evident that this sugar in Golang have to be used with moderation, for me, personally, I like to use this sugar with max of one level of nesting, like:
var number int64
if v := os.Getenv("NUMBER"); v != "" {
number, err = strconv.ParseInt(v, 10, 64)
if err != nil {
os.Exit(42)
}
} else {
os.Exit(1)
}
You can also implement ternary expressions with functions like func Ternary(b bool, a interface{}, b interface{}) { ... } but i don't like this approach, looks like a creation of a exception case in syntax, and creation of this "features", in my personal opinion, reduce the focus on that matters, that is algorithm and readability, but, the most important thing that makes me don't go for this way is that fact that this can bring a kind of overhead, and bring more cycles to in your program execution.
You can use a closure for this:
func doif(b bool, f1, f2 func()) {
switch{
case b:
f1()
case !b:
f2()
}
}
func dothis() { fmt.Println("Condition is true") }
func dothat() { fmt.Println("Condition is false") }
func main () {
condition := true
doif(condition, func() { dothis() }, func() { dothat() })
}
The only gripe I have with the closure syntax in Go is there is no alias for the default zero parameter zero return function, then it would be much nicer (think like how you declare map, array and slice literals with just a type name).
Or even the shorter version, as a commenter just suggested:
func doif(b bool, f1, f2 func()) {
switch{
case b:
f1()
case !b:
f2()
}
}
func dothis() { fmt.Println("Condition is true") }
func dothat() { fmt.Println("Condition is false") }
func main () {
condition := true
doif(condition, dothis, dothat)
}
You would still need to use a closure if you needed to give parameters to the functions. This could be obviated in the case of passing methods rather than just functions I think, where the parameters are the struct associated with the methods.
As everyone else pointed out, there's no ternary operator in Go.
For your particular example though, if you want to use a single liner, you could use Max.
import "math"
...
c := math.Max(a, b)
Ternary ? operator alternatives | golang if else one line
You can’t write a short one-line conditional in Go language ; there is no ternary conditional operator.
Read more about if..else of Golang

Resources