Introduction to Go Language
Simplicity is the essential design philosophy of Go. The language features are apparent and similar to the C language, yet are considered easier to use while hiding the complexity of designing and implementing them. The following are some of the complex features that Go makes very simple.
Go provides a rich static type system, allowing developers to define new types over built-in basic and composite types.
The following basic types are available in Go:
- Built-in string type: string
- Built-in boolean type: bool
- Built-in numeric types: int8, uint8 (byte), int16, uint16, int32 (rune), uint32, int64, uint64, int, uint, uintptr, float32, float64, complex64, complex12
Furthermore, Go supports the following composite types:
- pointer types – similar as in C
- struct types – identical as in C
- function types – functions are first-class types in Go
- array types – fixed-length container types
- slice type – dynamic-length container types
- map types – maps are associative arrays
- channel types – channels are used to synchronize data among goroutines
- interface types – interfaces play a crucial role in polymorphism
New types can be defined on existing types using the keyword type.
The following example shows different type definitions using built-in basic and composite types.
Embedding and Interfaces
Go is not an object-oriented language in the classical sense, as there are no classes Go has no concept of inheritance. Instead, Go focuses on composition (achieved through type embedding) and polymorphism (achieved through interfaces).
Type embedding is achieved by including a type name as a parameter within another type. This way, the embedded type fields, and methods will be available from the new type. In the following example, the type Professor embeds the type Employee.
As a result, the type professor’s variable pr can access the Salary field and the Work method defined on the embedded type.
Apart from type embedding, Go provides runtime polymorphism through interfaces. Interfaces are a particular class of types defined as a set of method signatures. Interfaces can be implemented implicitly by any other type.
In the following example, types Square and Rectangle implement implicitly (by implementing the Area method) the Shape interface. No explicit keyword, as in other languages, is necessary. As a result, any variable of type Square or Rectangle can be used as a variable of type Shape.
The built-in concurrency support is one of the most attractive features of Go. Go provides a very minimalist approach to utilizing concurrency while eliminating many of the considerations that come with it. The primary construct of concurrency is the goroutine. Goroutines are lightweight virtual threads that are maintained and scheduled by the Go runtime. Simply prefixing a function call with the go keyword, starts the function in a new goroutine in the background. Each program has at least one goroutine (the main function runs in one).
Apart from goroutines, Go introduces channels, typed objects that are used to communicate messages between different goroutines. Goroutines and channels together provide an elegant way of structuring concurrent code. Instead of explicitly using concurrency mechanisms such as locks to mediate access to shared data, Go encourages the use of channels to share data between goroutines. By design, only one goroutine has access to a shared value on a channel at any given time, so race conditions cannot occur. This design philosophy boils down to the slogan:
Do not communicate by sharing memory; instead, share memory by communicating.
The following example shows the usage of goroutines and channels to write a simple concurrent program.
In this video from our Fyber Inspiration series, Orgest Xhelili introduces us to the topic of Go.
Fyber’s Inspiration sessions are regular meetings in which our subject matter experts share their knowledge of the latest technologies with other Fyber employees and now we can share with you.