From PHP to Go: the isset function

This is the second part of the series From PHP to Go, a quick and dirty guide for all those who come from PHP and are getting started with this fantastic language. The first part was about arrays, slices an maps.

A common question from many PHP developers who switch to Go is if there is any similar function to the PHP isset() function in Go.

Answer: no, there isn’t. But you don’t need a function to do this in Go. There are different methods to check if a variable is set and if it is not null.

How to check if a variable exists in Go?

There are two things you must know:

First, for most of the cases, if the variable does not exist at all, your code won’t even compile, so there is no need for you to extra check that. You will see the problem “undefined variable” and the exact part of the code where you are calling this variable. Your IDE may also warn you about this error before even trying to compile.

Note that I said “in most of the cases”, since there are some situations as we will see later where the compiler can not know if the variable exists or not.

This will not compile:

package main

import (
    "fmt"
)

func main() {
    fmt.Println(foo)
}
Compiler output: "test.go:8:17: undefined: foo"

Second, remember that non-initialized variables or empty variables are not nil by default (nil is the Go equivalent of NULL) but are set to “zero values” according to the type of the variable. For instance, if you declare a variable of type integer, but you don’t assign any value to it, its value will be set by default to 0. For a string, the default value will be “”, and for a boolean, it will be false. Maps are however nil if they are not initialized.

var i int       // 0
var f float64   // 0
var b bool      // false
var s string    // ""

There are some occasions where the compiler cannot know if a variable exists or not. This is the case of arrays, slices, and maps, where the element of those variables can be dynamically created.

Check if an index exists in a map:

If you are trying to check if a key exists in a map, you could do the following:

foo := map[string]string{"first": "Sunday", "second": "Monday", "third": "Tuesday"}
 
// We want to check if the key "first" exists: 
if _, ok := foo["first"]; ok {
    fmt.Println(foo["first"])
}

Calling an item of a map by its key returns two values: the first is the value of this key, the second is a boolean indicating if this key exists or not:

value, exists = foo["first"] // value = "Monday", exists = true
value, exists = foo["nine"] // value = "", exists = false

If you want to check if a particular element exists by its value, you will have to iterate over the map:

foo := map[string]string{"first": "Sunday", "second": "Monday", "third": "Tuesday"}

for key, val := range foo {
    if val == "Monday" {
        fmt.Printf("Yeah, it is %s, and its key is: %s", val, key)
    }
}

Ranging over the slice returns the key as a first element and the value as the second.

Check if an item exists in a slice

As we saw on the first part of this series, slices have no key/value pairs in Go, so you can’t look for their key.

There are a few solutions here depending on what exactly you need to do.

The most common is to iterate the slice exactly as mentioned above in maps:

var slice = []string{"Monday", "Tuesday", "Wednesday"}
for key, val := range slice {
    if val == "Monday" {
        fmt.Printf("Yeah, it is %s, and its key is: %d", val, key)
    }
}

But if you only need to check if there are X number of elements on this slice or if the element number X exists, you can just use len()

var slice = []string{"Monday", "Tuesday", "Wednesday"}
if len(slice) == 7 {
    fmt.Println("This week has 7 days")
} else {
    fmt.Println("This is a very short week")
}

Check if an item exists in an array

Like slices, arrays have no key/value pairs, so you can’t look for their key.

You can’t use the len() method either because the number of elements declared will always exist and their values set to zero-value if any value has been assigned to them yet:

week := [7]string{}
if len(week) == 7 {
    // This is true, the week array has 7 elements, no matter if they are empty! 
}

So, for arrays, you could use the range iteration as mentioned above (I won’t repeat it here). In case this is fine for what you want to do, you can also check if the items have the zero value since this could mean the items “have not been yet set”:

week := [7]string{}
if week[2] == "" {
    // The second element on week has its zero value, so maybe "it wasn't set" yet
}

That’s all folks!


goPHP

849 Words

2019-03-06 08:00 +0100