Category Programming

Go libs I don't use but are popular
4 min read

Introduction

In the Go programming ecosystem, developers have a plethora of libraries available for solving common problems. However, some libraries may not always be the best fit for every project or developer preference. This article highlights a few Go libraries that I personally avoid using, along with the reasons behind these choices. The intention is not to discourage the use of these libraries universally but to shed light on potential challenges that may arise when using them, especially in larger or more complex projects.

Testing code with unpredictable or random output
4 min read

Introduction

In this blog post, I want to share my approach to testing functions involving randomness in Go. Recently, I was asked how I would test a specific function that calculates possible directions for an object to move. Initially, I didn’t come up with a good idea. Here, I’ll discuss how I’d solve this problem in a real-world application with a detailed explanation.

The Function in Question

The function calculates all possible directions that an object can move (up, down, left, right) without violating boundaries. It then randomly selects a valid direction and returns the new coordinates.

How to hash and compare passwords in Go
0 min read

The best to hash passwords in Go is using golang.org/x/crypto/bcrypt:

func HashPassword(password string) (string, error) {
    bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    return string(bytes), err
}
  
func CheckPasswordHash(password, hash string) bool {
    err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
    return err == nil
}

You should use the default bcrypt.DefaultCost just in case that the current value will become not sufficient and the default cost will increase.

How to gather GC metrics in NodeJS
1 min read

We can trace NodeJS GC by using

  node --trace-gc app.js

And use the performance tool to get the data in runtime.

  const { PerformanceObserver } = require('perf_hooks');
  
  // Create a performance observer
  const obs = new PerformanceObserver((list) => {
    const entry = list.getEntries()[0]
    /* 
    The entry would be an instance of PerformanceEntry containing
    metrics of garbage collection.
    For example:
    PerformanceEntry {
      name: 'gc',
      entryType: 'gc',
      startTime: 2820.567669,
      duration: 1.315709,
      kind: 1
    }
    */
  });
  
  // Subscribe notifications of GCs
  obs.observe({ entryTypes: ['gc'] });
  
  // Stop subscription
  obs.disconnect();

To gather memory usage we can use the following code

Memory-wall problem: cache locality in Go
9 min read

The memory wall problem refers to a phenomenon that occurs in computer architecture when the processor’s speed outpaces the rate at which data can be transferred to and from the memory system. As a result, the processor must wait for the data to be fetched from memory, which slows down its performance and limits its speed.

The memory wall problem has become increasingly significant as processors have become faster and more powerful while memory speeds have not kept pace with these advancements. This means that even though the processor can execute instructions quickly, it spends a significant amount of time waiting for data to be transferred to and from memory.

Why We Should Avoid Using `else` in Programming
3 min read

The else keyword is a commonly used control structure in programming. It allows us to execute a block of code if a condition is not true. However, overusing else statements can lead to less readable and maintainable code. In this article, we’ll explore why we should avoid using else clauses in our code and look at some alternatives that can make our code more concise and readable.

Why Overusing else is a Bad Idea

One of the main arguments against using else statements is that they can make our code more complex and harder to read. As the number of conditions and branches increases, the code becomes harder to understand and maintain. Additionally, else clauses can make it difficult to follow the control flow of a program.

Writing tests in Go (business apps)
9 min read

There are many practices and tactics that tackle testing. Today, I’ll share with you how I write tests for my projects. Please notice that you may find it useful when starting a new project or an independent part of existing applications. You may find it difficult to apply in an already existing application. It’s not impossible but it may be challenging.

General rules for tests

Works out of the box

When someone clones our project, the person should be able to run basic tests without any setup. It’s a good thing when you have an open-source project as well as when you have a new team member. Or even for you after you reinstall your PC. I remember many projects where I had to spend a day or two to make it work and actually start developing something. It’s frustrating when you have to manually set up a DB connection, get proper permissions to an AWS account, configure it correctly, and so on.

Top level logging
5 min read

I like having the core logic of our application free of distractions like too many technical “details” like logging or generating metrics. Of course, sometimes it’s hard to avoid it. I found in many projects a situation where we put the logger very deeply inside of the code. At the end of the day, we had the logger almost everywhere. In tests, we had to provide the mocked implementation everywhere as well. In most cases, the logger is a redundant dependency. In this article, I’ll argue that we should have the logger only in top-level functions.

`replace` directive in go modules
1 min read

Sometimes, we may want to use a library but a slightly modified version. It happens very often when we develop the library but test it in the context of an application. Go has a handy mechanism in go modules that can help us with it.

To make it work, we have to clone the library somewhere near the target project and run the following command in the application’s folder.

go mod edit -replace github.com/my/library ../path

The path can be both relative (to the application root folder) or absolute. The go.mod file will be edited as follows.

gRPC with SSL/TLS
2 min read

gRPC supports authentication. Adding it to your project is simple. All you have to do is configure it with just a few lines of code. One of the authentication types that gRPC supports is SSL/TLS. From the server-side, the code looks like this:

creds, err := credentials.NewServerTLSFromFile(certFile, keyFile)
if err != nil {
    // handle the error - no ignore it!
}
s := grpc.NewServer(grpc.Creds(creds))

The client has to update the code as shown below.

creds, err := credentials.NewClientTLSFromFile(certFile, "")
if err != nil {
    // handle the error - no ignore it!
}
conn, _ := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(creds))

But, from where take the certificate? One of ways is using the openssl.