One of Go’s initial design requirements was to make it easy to create multi-threaded applications. While many languages support multi-threading, it’s not always easy to implement. Go wanted to make it easy to do this.
Consider the following code where it runs sequentially.
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Starting App")
callSequentially()
}
func PrintHello(msg int) {
fmt.Print("Hello! ")
fmt.Print(msg)
fmt.Println("")
}
func callSequentially() {
fmt.Println("Calling Sequentially")
defer timeTrack(time.Now(), "Sequentially")
for i := 0; i < 100; i++ {
PrintHello(i)
}
}
// neat little function to determine how long something takes to process in go
func timeTrack(start time.Time, name string) {
elapsed := time.Since(start)
fmt.Printf("%s took %s\n", name, elapsed)
}
If you run this, every function call to PrintHello() has to complete before it returns to the loop to finish executing. There is a lot of overhead involved in that, and it makes it relatively slow.
However, with a slight modifictation, you dramatically improve performance.
func main() {
fmt.Println("Starting App")
callWithGoroutine()
time.Sleep(2 * time.Second)
}
func callWithGoroutine() {
fmt.Println("Calling With Threads")
defer timeTrack(time.Now(), "Threads")
for i := 0; i < 100; i++ {
go PrintHello(i)
}
}
If you look at them, you may not see what the difference is. However, upon closer inspection, you can see there is a go
command before the function. This tells go, the language, to start a thread for that function call. With each function call being put in a thread, it can execute as it needs, and the loop performs much… much… much faster.
The Minor Issue…
There are a couple of issues that people run into when they use threads. One of which is timing regarding output. If you run the two, you will notice the first one is much slower than the goroutines version. However, you might notice that because PrintHello()
uses multiple print statements, they don’t always print in order with the other print statements of that thread instance.
To avoid these types of issues, go uses something it calls channels.
Goroutines and channels was originally found on Access 2 Learn