Golang – labeled break and continue

break and continue are keywords that control the loop in many programming languages. The scope of those keywords is at inner most. Here is the example code of C++.

for (int i = 0; i < 5; ++i) {
    for (int j = 0; j < 5; ++j) {
        if (i == 1 && j == 3) {
            break;
            // continue;
        }
    }
}

In the example code above, break and continue will only affect the inner most loop which deals with the variable j. However, in golang, you can control the scope of break and continue keyword by using labels.

Here is the example code.

package main

import (
	"fmt"
	"os"
	"strings"
)

func main() {
	library := `
	I am learning computer science and computer engineering
	`
	words := strings.Fields(library)
	query := os.Args[1:]

queries:
	for _, q := range query {
		for i, w := range words {
			if q == w {
				fmt.Printf("index %d: %q\n", i, w)
				break queries
			}
		}
	}
}

Let’s say there is a library of words and you are querying unique words. For example, when you query the word computer, it should return the first index of the word and the word itself. As you are running the loop, there are multiple ways to achieve this. But I want to show you that you can use a label to control the scope. You can declare the label at any scope you want and use the label with break or continue keyword. As you see in the above code, it will exit the entire thing once it finds the word.

go run main.go computer
index 3: "computer"

Go Lang – Printf Cheat Sheet

This is a go lang Printf cheat sheet post. Essentially it is very similar to the one in C. Just like the one in C, Printf really prints the string in a formatted way. It is very convenient to have a cheat sheet since I always forget unless I use it frequently. This mainly focuses on examples.

print type of variable %T

var intNum int
var floatNum float64
var boolVal bool
var strVal string

fmt.Printf("%T\n", intNum)
fmt.Printf("%T\n", floatNum)
fmt.Printf("%T\n", boolVal)
fmt.Printf("%T\n", strVal)

// output
int
float64
bool
string

print int type %d

This prints integer type. It will perform type check and will give you a warning that type doesn’t match. And of course the result format will be odd.

age := 21
fmt.Printf("age: %d\n", age)
fmt.Printf("age: %s\n", age)

// output
age: 21
age: %!s(int=21)

print float %f

%f prints floating numbers. Since this is a floating number, you can control the precision with “.<number>”
Increasing precision means the floating number will be more precise.

floatNum := 224.701
fmt.Printf("num: %f\n", floatNum)
fmt.Printf("num: %.0f\n", floatNum)
fmt.Printf("num: %.1f\n", floatNum)
fmt.Printf("num: %.2f\n", floatNum)
fmt.Printf("num: %.3f\n", floatNum)
fmt.Printf("num: %.4f\n", floatNum)
fmt.Printf("num: %.5f\n", floatNum)

// output
num: 224.701000
num: 225
num: 224.7
num: 224.70
num: 224.701
num: 224.7010
num: 224.70100

print bool %t

male := true
female := false

fmt.Printf("are you male?: %t\n", male)
fmt.Printf("are you femail?: %t\n", female)

//output
are you male?: true
are you femail?: false

print string type %s, %q

Those print the strings. However, there is a difference between them. %s just prints the string itself but %q prints with double quotes.
Note that \n is just an escape sequence providing a new line. This also performs type checks.

name := "Google"
fmt.Printf("%s\n", name)
fmt.Printf("%q\n", name)

// output
Google
"Google"

print any value %v

This prints all the provided values. It’s very convenient but it doesn’t guarantee any type safety. For example, what if you only want to print int instead of string or float? %v will not check anything and print as-is.

name := "Google"
val := 1
floatVal := 1.123
fmt.Printf("%v %v %v\n", name, val, floatVal)

// output
Google 1 1.123

Argument Index

Typically you have to provide a value for each verb in the Printf format string. However, there is an exception to this rule. You can refer to the already provided variable. This is called argument index. Note that [1] refers to the first argument which is “name”. [2] refers to the second argument. Why does the index start from 1? It’s because index 0 of the Printf is the format string.

name := "NY Comdori"
job := "software engineer"

fmt.Printf("%v is a %v. Being %[2]v is fun! Good luck %[1]v!\n", name, job)

// output
NY Comdori is a software engineer. Being software engineer is fun! Good luck NY Comdori!

Go lang – iota and constants

In programming languages such as C++ and Java, there is Enum type which is used frequently. In go language, you can use iota to represent an Enum type.

Let’s take a look at a simple example

Example

Let’s say you want to define variables to represent weekdays. In that case, you probably just want to have integer values for a simple comparison. (You really don’t want to use string to represent the value unless you are printing) Let’s take a look at a version that naively represents the weekdays.

const (
	SUNDAY = 0
	MONDAY = 1
	TUESDAY = 2
	WEDNESDAY = 3
	THURSDAY = 4
	FRIDAY = 5
	SATURDAY = 6
)

// output
fmt.Println(SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY)

0 1 2 3 4 5 6

Now it will perfectly fine because you can use those variables like others. However, it is very tedious to explicitly type all the values because you really don’t care about those. You just want consecutive integers. Here is where iota comes into play to make life better.

What is iota? It is a built-in constant generator that generates consecutively increasing numbers. Let’s take a look at the usage

const (
	SUNDAY = iota
	MONDAY
	TUESDAY
	WEDNESDAY
	THURSDAY
	FRIDAY
	SATURDAY
)

// output
fmt.Println(SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY)

0 1 2 3 4 5 6

With iota, you only need to assign iota once to the place you want to generate. iota always starts from 0 and will increase the number and repeat the same assignment as the previous line. In the example above, SUNDAY will be 0. For MONDAY, iota will repeat itself with the increased number which is 1. It will stop once it reaches the end and the value will be reset to 0 so that it won’t disrupt other constant settings. What happens if you want to use iota from the middle part?

const (
	SUNDAY = -1
	MONDAY = iota
	TUESDAY
	WEDNESDAY
	THURSDAY
	FRIDAY
	SATURDAY
)

// output
fmt.Println(SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY)
-1 1 2 3 4 5 6

You just have to explicitly set the value before the iota usage. iota will start from there. Note that iota value starts from 1 instead of 0.
Why is that? It’s because iota starts from the beginning of the constants.

Blank Identifier

You can use a formula to set a custom value using iota. iota always starts from 0 and if you want a different value, you have to use some expression to do that. Let’s say you want to represent different timezones in constants. You only want to represent three timezones in the U.S. – EST, MST, PST – compared to UTC. For example, EST means the eastern standard time that is -5 hours behind UTC. MST means mountain time that is -7 hours behind UTC. PST means the pacific time that is -8 hours behind UTC. Therefore you want to have your constants represent like this.

const (
	EST = -5
	MST = -7
	PST = -8
)

fmt.Println(EST, MST, PST)
-5 -7 -8

But how can you use iota here? There are two issues here. iota will return a non-negative increasing number but you want to have negative numbers here. The second issue is that the values we want are not consecutive. Let’s tackle the issue one by one. How can we have negative numbers using iota? We can use a formula to manipulate the value.

const (
	EST = -(iota + 5)
	MST
	PST
)

fmt.Println(EST, MST, PST)
-5 -6 -7

You can use a typical mathematical expression when using iota because it just returns a number.

Now, there is still an issue here. We want -5, -7, -8 but actually got -5, -6, -7 because iota only returns consecutively increased numbers. What can we do? Remember that iota will always increase the value in every line. But We certainly don’t want to declare any dummy constant just for that. Blank identifier comes to the rescue. Blank identifier in go is to tell the compiler this is unused variable and ignore it. It is ‘_’.

const (
	EST = -(iota + 5)
	_
	MST
	PST
)

fmt.Println(EST, MST, PST)
-5 -7 -8

Now, note that iota will increase by 1 at line 3. We all know that ‘_’ is a dummy and can just ignore. In MST, it will be set to -7 which is the correct value now.

Conclusion

We have briefly taken a look at iota and constants in go lang. It could be pretty convenient when used properly. Happy coding!