The Greatest Generation and My Uncle Bill

I missed the last reunion but tomorrow, I’ll be on the R train headed for Bay Ridge to visit my brother, my sister-in-law, my father’s third wife, and most of all…my 99-year-old Aunt Ellie! Her late…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Golang for C developers

I have a strong background in real time / c development. For a recent project that I started working on I decided to pick up golang. Mainly to give the language a try and see what all the fuss is about. Coming from C background there are considerable differences from other developers. Most low level developers will put more emphasis on how things work “under the hood”.

In this post I have documented the beginning of my journey with learning go. Sharing things that I found interesting along the way.

TL;DR: Read a good book

Whenever I learn a new technology I tend to look for a good book on the topic. Books have the main benefit of being written by professional authors. They are also edited by professionals and tend to do a good job in making content approachable for the readers. I find that for me this approach works better than reading official documentation or participating in courses.

This brings me to the book I chose this time. I had a few requirements in mind

Its all about memory management right? Gotta love your RAM

TL;DR: Go automatically decides what to allocate on the stack / heap. It is performed by compiler logic and as such it can differ between versions of the compiler.

One of the things that every C developer thinks about right away is memory management. How is it managed in Go? Can developers control where their data is allocated and managed?

First thing to note here is that go has a garbage collection mechanism. That means that memory allocated by applications is handled by the go runtime. The next thing to note is that go tries to store as much as it can on the stack. But, the developer has no implicit control on whether an object is allocated on the stack or on the heap.

Note: The stack of each go routine is resizable this means that even that a variable is stored on the stack it might be moved by the compiler to a different location. Once the stack of a specific go routine is depleted the go runtime will copy the stack to a new buffer. By doing that all pointers to the previous location on the stack are no longer valid. No worries, this doesn’t mean that if you take a pointer to a stack that can be affected by this the program will crash. The go runtime has built in logic for updating the value of these pointers. The pointers will be updated to point to the new address on the stack.

Note: In order to understand if your version of the compiler allocates a variable on the stack or on the heap use -m compilation flag.

The following code examples demonstrate the effects on the stack

Example output of -m:

Another interesting point is to return a pointer to a locally defined variable. In such a case the go compiler will detect that the variable escapes the scope and thus it will be allocated on the heap.

For further reading I highly recommend reading the following posts:

TL;DR: defer is a way to trigger cleanup logic at the end of a function.

Golang tries to make code more readable as a design goal. One of the mechanism used in the language for this purpose is the defer mechanism. The defer mechanism is a way to handle cleanup logic. For example, lets assume that a function calls open and wants to verify the resource is properly cleaned. This means that we will need to include a call to close somewhere later in the function. In case our function gets complicated and have multiple return points we need to make sure that we invoke close in all needed paths. By using defer we add the cleanup logic directly after the creation. Since the deferred logic will be executed at the end of the function we can be sure that it will be executed.

The following pseudo code illustrates the example from the last paragraph:

The defer implementation allows you to specify multiple cleanup actions in a single function. This is achieved by a simple stack. On the level of each function there is a logical stack, every time a new defer invocation is made the cleanup logic is pushed into the said stack.

The following code snippets shows a few examples for defer usage

For a few more tricks regarding defer in go refer to the following:

TL;DR: Go provides a built in interface mechanism. The interface is essentially a collection of function pointers. The beauty in go is that interfaces are implicit.

The following example showcases simple usage of interface. The main thing to notice here is that the struct, foo in this case, doesn’t mention the interfaces in any place

The fact that the interface definition and the logic implementation are separate is great. It is possible to define multiple interfaces, that exposes only the needed functionality for a given module. That can simplify implementing mocks for tests. The fact that it has no impact on external parts of the code base make it simple to use multiple interfaces on the same object.

Note: as you might have expected, interfaces imply dynamic dispatching. That means that the runtime has to perform some adaptations to the addresses of the functions to make it work. This is an added cost for every invocation via an interface.

Note: go interfaces use pointers under the hood. This results in that in most cases if an interface is used the compiler will assume that the variable escapes the stack. Thus, the variable will most likely be allocated on the heap.

For further reading:

TL;DR: Golang enforces removal of dead code. It is a compilation error to import a package and not use it

As projects grow and code is moving around it is very common to find #include statements that are not relevant. This slows down compilation speeds by creating redundant work for the compiler.

One of the most famous features of go is the go routines. This is a mechanism that allow running a given function as a fiber. These fibers are managed by the scheduler of the go runtime. Note that these fibers are not operating system level threads. The go runtime spins up one or more operating system threads and schedules the routines on these threads.

One of the scheduling mechanisms that is most commonly used in golang is called channels. A channel is essentially a FIFO. One, or more, go routines write to the channel while one, or more, go routines read from the channel.

The following example demonstrates a few go routines communicating with each other via channels

Summary

During my initial review I learned quite a few things about go lang.

The good:

The bad:

At the time of writing this blog I mostly see golang as an alternative to python. That is, a language that is suited for various management applications. Time will tell how and where it will fit in my future projects.

Useful tools

Add a comment

Related posts:

Back propagation

One of the main steps in our machine learning algorithm is to set best weights to model. set in the sense is that we have to find those from the training the model with training examples…

Keto Creatine is safe ?

Keto Creatine. No matter whether you are a newbie in the gym or a seasoned athlete with years of experience, if you’re keeping an eye on the news and discussions in the fitness world. You have…

EveryLibrary Helps Libraries Win Funding

EveryLibrary supports libraries facing funding challenges free of charge. When the McCall Public Library in McCall, Idaho, faced the daunting task of getting the city to pass a bond they reached out…