The strace(1) command-line utility allows you to trace system calls and signals. As strace(1) is not available on Mac machines, this section will use a Linux machine to showcase strace(1). However, as you will see in a later, macOS machines have the dtrace(1) command-line utility that can do many more things.
The number after the name of a program refers to the section of the manual its page belongs to. Although most of the names can be found only once, which means that putting the section number is not necessary, there are names that can be located in multiple sections because they have multiple meanings, such as crontab(1) and crontab(5). Therefore, if you try to retrieve such a page without specifically stating the section number, you will get the entry in the section of the manual that has the smallest section number.
To get a good sense of the output generated by strace(1), look at the following figure where strace(1) is used to examine the executable of addCLAImproved.go:
Using the strace(1) command on a Linux machine
The really interesting part of the strace(1) output is the following line, which cannot be seen in the preceding figure:
We used the grep(1) command-line utility to extract the lines that contain the C system call that interests us, which in this case is write(2). This is because we already know that write(2) is used for printing output. So, you learned that in this case, a single write(2) C system call is used for printing all of the output on the screen; its first parameter is the file descriptor, and its second parameter is the text you want to print.
Note that you might want to use strace(1) with the -f option in order to also trace any child processes that might get created during the execution of a program.
Bear in mind that there exist two more variations of write(2), named pwrite(2) and writev(2), which offer the same core functionality as write(2) but in a slightly different way.
The following variation of the previous command requires more calls to write(2) because it generates more output:
Unix uses file descriptors, which are positive integer values, as an internal representation for accessing all its files. By default, all Unix systems support three special and standard filenames: /dev/stdin, /dev/stdout, and /dev/stderr. They can also be accessed using file descriptors 0, 1, and 2, respectively. These three file descriptors are also called standard input, standard output, and standard error, respectively. Additionally, the file descriptor 0 can be accessed as /dev/fd/0 on a Mac machine and as /dev/pts/0 on a Debian Linux machine because everything in Unix is a file.
So, the reason for needing to put 2>&1 at the end of the command is to redirect all of the output, from standard error (file descriptor 2) to standard output (file descriptor 1), in order to be able to search it using the grep(1) command, which searches standard output only. Note that there exist many variations of grep(1), including zegrep(1), fgrep(1), and fgrep(1), that might work faster when they have to deal with large or huge text files.
What you can see here is that even if you are writing in Go, the generated executable uses C system calls and functions because apart from using machine language, C is the only way to communicate with the Unix kernel.