They are green threads – lightweight threads managed by the Go runtime, not by the operating system. Goroutines are the basic building block for concurrency in the Go language. To do that, we’ll spawn ten goroutines and have each of them withdraw one tenth of the money. Now let’s make the benchmark concurrent, to model different users making withdrawals at the same time. We can ignore the “no tests to run” warning, which refers to the unit tests we didn’t write (in later Go programming examples in this tutorial, the warning is snipped out). We ran two billion (!) iterations, and the final check on the balance was correct. Burn through them one at a time until they are all goneī.Error("Balance wasn't zero:", fund.Balance()) Add as many dollars as we have iterations this run To ensure this, it will call the benchmark multiple times, passing in an increasing “number of iterations” value each time (the b.N field), until the run takes at least a second.įor now, our benchmark will just deposit some money and then withdraw it one dollar at a time. The testing framework wants each benchmark to run for at least 1 second (by default). This allows the framework to time how long each iteration takes, averaging out transient differences from disk seeks, cache misses, process scheduling, and other unpredictable factors.
GOLAND IDE TUTORIAL CODE
The simple logic in our Fund isn’t really worth writing unit tests for, but since we’ll be talking a lot about concurrent access to the fund later on, writing a benchmark makes sense.īenchmarks are like unit tests, but include a loop which runs the same code many times (in our case, fund.Withdraw(1)). Rather than writing a separate program, we’ll use Go’s testing package, which provides a framework for both unit tests and benchmarks. Methods start with a *receiver*, in this case a Fund pointer whether it's on the stack or heap: Go figures that out for us. We can return a pointer to a new struct without worrying about A regular function returning a pointer to a fund balance is unexported (private), because it's lowercase Instead, we’ll declare a struct type called Fund, with a simple function to create new fund structs, and two public methods. Go is deliberately not an object-oriented language: There are no classes, objects, or inheritance. The fund starts with a given balance, and money can only be withdrawn (we’ll figure out revenue later). Let’s write some code to track our startup’s funding. As we progress through our Go tutorial, we’ll encounter lots of cool Go language features, including: To demonstrate this in practice, we’ll build the service in small steps, making a mess along the way and then cleaning it up again. We’ll use a Fund type as an example – a simple store for our startup’s remaining funding, where we can check the balance and make withdrawals. In today’s Go programming tutorial, we’re going to look at one such abstraction: A wrapper which can turn any data structure into a transactional service. In many cases, a handful of reusable abstractions over those low-level mechanisms makes life much easier. While Golang has an excellent set of low-level features for handling concurrency, using them directly can become complicated. This means skilled Go programmers need to deal with concurrent access to those resources. An obvious example is a webserver: Every request runs separately, but requests often need to share resources such as sessions, caches, or notification queues. Go is also a great language for writing concurrent programs: programs with many independently running parts. There is exactly one correct way to lay out Go code, enforced by the gofmt tool. It downplays exception handling in favour of explicit errors in return values.
It omits OOP idioms such as inheritance and polymorphism, in favor of composition and simple interfaces. Meanwhile, Golang takes a strong position on features that can lead to confusion and bugs. For that, we need interfaces, which we'll encounter briefly later. While `A` may have a `B`, that doesn't mean it is a `B` - functions which take a `B` won't take an `A` instead. Promoting methods in this way is called *forwarding*, and it's not the same as subclassing: the method will still be invoked on the inner, embedded struct.Įmbedding also doesn't imply polymorphism. *Mixins* are available by embedding structs anonymously, allowing their methods to be called directly on the containing struct (see embedding). Still, many of the useful parts of OOP are available in other ways. It has no subclassing, and so there are no inheritance diamonds or super calls or virtual methods to trip you up. OOP is one of those features that Go deliberately omits.