Three efficient programming skills in Go language

Click on the blue "Flying Snow Ruthless" above to follow me, set a star, and read the article as soon as possible

Go is a very nice programming language. It's a language that lets you really focus on your business and not on the program itself, so you can write applications as quickly as possible. For example, it has a relatively complete ecosystem that can provide you with everything you need to get started.

However, it is not a panacea, and there are some things that need our attention. I wrote this article mainly to remind myself, but also some observations and conclusions. Of course, these are just tips, not real problems, of course, if you pay attention to them and use them in actual combat, it will benefit you a lot. This is the difference between a novice and a veteran.

Don't use Logrus

This is actually related to generics. Because Go is a strongly typed static language, you cannot bypass data types like NodeJS or PHP. So what if we still need to use generic types? For example, like Loger, or ORM, because only when a common type is used can a common code be written, otherwise each one has to be written once.

In the end, we can only use reflection. Whereas Logrus makes heavy use of reflection, which results in a large allocation count. While usually not a huge issue (depending on the code), performance matters, especially in large-scale, highly concurrent projects. While this sounds like a very small optimization, it's important to avoid reflections. If you see some code that can use structs regardless of type, it uses reflection and has a performance hit.

For example, Logrus doesn't care about types, but apparently Go needs to know (eventually). What about Logrus? Use reflection to detect the type, which is overhead.

log.WithFields(log.Fields{
    "animal": myWhatever,
  }).Info("A walrus appears")

So I would prefer zerolog, of course zap is also good. Both declare zero allocation, which we also want since they have the least performance impact.

Do not use encoding/json

When we need a function, a function, many people suggest using the standard library. But the encoding/json module in the standard library is an exception. In fact, like the above example, encoding/json uses reflection, which will lead to poor performance and will cause losses when writing APIs or microservices that return json responses.

For example you can use Easyjson, it's simple and efficient, it uses a code generator to create the code needed to convert the structure to json to minimize allocations. This is a manual build step and annoying. Interesting that json-iterator also uses reflection, but is significantly faster, I suspect black magic.

Avoid using closures in goroutines whenever possible

For example, the following sample code:

for i:=0;i<10;i++ {
  go func() {
     fmt.Println(i)
  }()
}

Most people would probably expect this to print the numbers 0 through 9, like when delegating tasks to goroutines.

But the actual result: depending on the system, you'll end up with one or two numbers and many 10s.

why? Closures have access to the parent scope, so variables can be used directly. Although newer linters may warn you about "captured by variable closures", they won't require you to redeclare the variable.

Go's performance reputation is largely due to the runtime optimizations performed, which try to "guess" what you want to do and optimize certain execution paths. During this time, it "captures" variables and passes them where they are needed in the most efficient way in theory (for example, after some non-concurrent operation is done to free an allocation on some CPU). The consequence in this case is that the loop may start goroutines which may receive the value of i from the parent scope much later. There's no guarantee which one you'll see when executing this code multiple times, it could be the number 10, or something else.

If you do use closures for some reason, be sure to pass the variable i and treat the closure as you would every function.

summary

There are definitely more than these three skills in programming practice. Exploring and mastering them in practice can improve our programming ability and allow us to write more optimized code.

This article is an original article, reprint and indicate the source, welcome to scan the QR code to follow the official account flysnow_orgor website https://www.flysnow.org/, and read the follow-up exciting articles as soon as possible. If you think it is good, please click "Looking" in the lower right corner of the article, thank you for your support.

—— Wonderful recommendation ——

Make a Caddy by hand (13) | Caddyfile parameters for plug-in development

Caddy combat (12) | Plug-in development of HelloWorld

  Caddy combat (11) | The beauty of Caddyfile design

Caddy combat (10) | Build a PHP server in one minute

Caddy combat (9) | Set header information to achieve cross-domain

Caddy combat (eight) | Use buffering to improve the performance of reverse proxy

Caddy Combat (7) | Health Check in Reverse Proxy

Caddy Combat (6) | Load Balancing in Reverse Proxy

Caddy combat (5) | Configure reverse proxy

Caddy combat (4) | Use API to manage Caddy

Caddy combat (3) | Caddyfile quick start

Caddy combat (2) | The most complete tutorial on Caddy command line parameters

Caddy combat (1) | host your website, just one line of command

31bf6a10496212269e2a5465f083cba7.png

Scan code attention

Share, like, watch is the biggest support

Guess you like

Origin blog.csdn.net/flysnow_org/article/details/125401481