Book Image

Network Automation with Go

By : Nicolas Leiva, Michael Kashin
Book Image

Network Automation with Go

By: Nicolas Leiva, Michael Kashin

Overview of this book

Go’s built-in first-class concurrency mechanisms make it an ideal choice for long-lived low-bandwidth I/O operations, which are typical requirements of network automation and network operations applications. This book provides a quick overview of Go and hands-on examples within it to help you become proficient with Go for network automation. It’s a practical guide that will teach you how to automate common network operations and build systems using Go. The first part takes you through a general overview, use cases, strengths, and inherent weaknesses of Go to prepare you for a deeper dive into network automation, which is heavily reliant on understanding this programming language. You’ll explore the common network automation areas and challenges, what language features you can use in each of those areas, and the common software tools and packages. To help deepen your understanding, you’ll also work through real-world network automation problems and apply hands-on solutions to them. By the end of this book, you’ll be well-versed with Go and have a solid grasp on network automation.
Table of Contents (18 chapters)
1
Part 1: The Go Programming Language
6
Part 2: Common Tools and Frameworks
10
Part 3: Interacting with APIs

Go versus Python

The topic of comparing programming languages can very quickly turn into a heated debate. We believe all languages have their merits and we don't want to advocate for one being better than the other. Still, we do acknowledge that most people with a network automation background would know and use Python, so it would make sense to present some form of comparison between the two languages and highlight some of their most salient points.

Code execution

One of the biggest differences that affect the developer experience is how you distribute and execute your code.

Python programs require an interpreter to run on a target machine and access to all library dependencies. While there are projects such as Nuitka to compile Python, you need commercial support to obfuscate your source code, for example. Having all source code available allows you to make changes and iterate quickly when developing a feature or troubleshooting a bug.

Go programs do not require an interpreter, as you distribute them as a compiled binary file. Compiling to machine code may seem like an unnecessary hurdle, but compilation takes only a few seconds, and the resulting binary has all its required dependencies, so it's the only file that needs to exist on the target system.

Type system

Go requires all variable types to be statically defined, with type inference allowed only during initial variable declaration.

Although generics are making their way into Go, they do not allow the same amount of freedom as a Python type system. A lack of explicit type declaration makes Python a more approachable language for beginners and for use cases where development speed is more important than code robustness. However, as Python projects become more mature, they must make up for these initial gains by putting more focus on testing.

Performance

Go programs perform better when compared to Python across a wide range of use cases (see The Computer Language Benchmarks Game: Further reading). This is, in part, an outcome of the points we already mentioned in this section, but it's also the result of the effort the Go team has put into optimizing the language.

While things such as goroutines and type definition give Go developers enough tools to write high-performance code, each Go release brings new improvements in memory management and compiler optimizations that make code execution faster in the background.

Ease of use

Python is a language designed to be used for teaching and prototyping. At the same time, it's versatile and powerful enough to write complex programs such as web servers (Flask, Django), machine learning (ML) frameworks (PyTorch, TensorFlow), and infrastructure software (RabbitMQ, Ansible).

As the number of Python projects you work on grows, maintaining different virtual environments for dependency and environment management might become a hassle. This is an area where Go shines, with its self-hosted dependency manager and statically linked binaries.

Despite that, Python continues to hold its dominant position as the most approachable language with a large open source community and is unlikely to relinquish it any time soon.

Memory management

Both languages use dynamic memory management with automatic garbage collection. Most of the time, you wouldn't need to and are not advised to change any of the default settings, although both languages expose a few threshold variables that can be fine-tuned if needed.

The biggest difference comes from the fact that Go allocates memory based on a more precise set of data types and that it does static memory allocation at compile time in the stack for goroutines and functions, and only a subset of variables escape to the heap. In contrast, Python treats everything as an object, so even the most primitive types, such as int or string, are considerably larger, and they are dynamically allocated memory at runtime (in the heap).

Access to memory in the heap is not only slower but also needs to be garbage-collected, which adds an overhead to the program execution.

Syntax

Python has a very lightweight syntax and uses indentation to separate different blocks of code. The lack of trailing semicolons and excessive curly braces make it comprehensible, but writing it without an IDE—which would automatically manage the indentation—can be a challenge.

Go never considered white space for indentation, as the language designers don't believe having your semantics depend on invisible characters is a good idea. This, of course, comes down to personal preferences; formats such as YAML Ain't Markup Language (YAML), for example, also use spaces to structure data.

Go benefits from its built-in formatting tool that auto-indents the code and makes it look neat by automatically inserting blank lines in certain places. Also, Go developers use blank lines to split logically separate a set of lines in a function that makes the final program less dense and easier to read.

Failure handling

Another big difference is in error handling. Python uses implicit error handling as a convention by relying on exceptions that can be carefully caught in parts of code where you expect them to happen. This keeps in line with Python's readability and ease-of-use nature. Go uses explicit error checks, and most functions have errors as the last positional return value. This often results in the code looking like this:

config, err := buildConfig(deviceName)
if err != nil {
   return err
}
 
d, err := connect(deviceName)
if err != nil {
   return err
}
 
if err := configure(d, config); err != nil {
   return err
}

Although this makes a program more robust by forcing the developers to always think about the returned error and act on it as soon as it happens, this does create a lot of visual noise that human brains quickly learn to ignore. This is a recurrent topic in the Go community and one of the areas that Go version 2 is putting a focus on. The Go 2 draft design document for error handling covers the problem and proposal in detail (Further reading).

Concurrency

Concurrency has not only been a feature of Go since day one but also one of the key drivers behind the creation of Go in the first place. Go has enough first-class language constructs to deal with most common concurrency challenges, such as communication between processes and access to shared resources.

By contrast, you cannot run more than two or more Python threads at the same time because the Global Interpreter Lock (GIL) prevents it, which the Python language designers made part of the language early on. This is unless you architect your program to use the threading library. The GIL has performance benefits for single-threaded programs, and removing it from the language has been a recurrent topic in the Python community.

To implement concurrency, Python makes you run multiple processes to leverage all the CPUs that you have at your disposal (multiprocessing or concurrency pools). Over time, different libraries have attempted to improve the performance and user experience (UX) of concurrency in Python, with the most popular one being asyncio.

Despite that, better concurrency and parallelism are in the top three most desired features to add to Python, according to Python Developers Survey 2020 Results (Further reading). Most Python developers don't like the current implementation, as writing concurrent code in Python can be challenging and requires the use of compatible libraries.

Community

Being the more popular language of the two, Python has a larger community with a huge number of open source libraries and frameworks. Although its major use cases are data analysis, web development, and ML (Python Developers Survey 2020 Results: Further reading), today you can find libraries that deal with anything from game development to desktop plugins.

Most importantly, Python is the most popular language for network automation and has amassed many libraries and frameworks to work with network devices. Go has been more systems- and performance-centric, so we don't see as many network libraries and tools. Still, one heavy user of Go in the network engineering community has been the OpenConfig ecosystem, which today includes almost a dozen different projects written in Go.

Go is being rapidly adopted by web-scale companies, which means we are likely to see more network-related projects appearing in the future.

We hope this gives you a perspective and appreciation of the Go language features. The next step is to install Go on your computer.