In the example below we use the gographics/imagick package as a wrapper to the C library for ImageMagick to convert our PDF into a JPG. The processes goes as follows: We use the package to load in our test file which we then process by setting the resolution, compression levels and alpha channel settings then we save the final output file. Because the library is built on C, it’s important we call the Terminate and Destroy functions appropriately to keep our memory usage in check.
In Go, although errors are a controversial subject, they are in fact very simple. As programmers of Go we also spend a lot of our time writing if err != nil. But we often also need to create these errors and pass them back to other functions to handle. The errors package allows to create errors, as per the error interface, which can be dealt with like any other error. In our example below we handle the error on main() and produce the error in DoSomething().
In Go, we use structs to define and group data, as we would use classes in other OOP languages. However, in Go the naming of attributes within the struct is important because if it starts with a lower-case it’s seen as private and with an upper-case first letter it’s seen as public. We can encode these structs into data formats like json but we might want to rename the fields, struct tags allow us to do this.
We’ve already got a post on converting an integer to a string but the process of converting a variable of type uint64 to a string is a little different. For an int we can use Itoa(), but for an unsigned int 64 we can still use strconv but we can use the FormatUint function instead.
The program below is designed to print out the current state of how much memory is being used, how much has been used and how much the system has reserved. You only really need the PrintMemUsage() function to do this, the rest of the main() is there to illustrate it working (with a gif showing this at the end of this post). The most important figure if often the Alloc which is the amount allocated heap objects.
In Go, the traditional while true loop, found in many programming languages, can done through the for keyword. Below are two alternative versions, a for can work as an infinite loop without any parameters, or with a true boolean.
We often need to measure execution time in programming, as it helps us understand the programs we’re working with and knowing where potential bottlenecks are occurring. In Go, we are able to use the time package and the defer keyword to run our time tracking function at the end of our long function. The parameters will be calculated at the beginning of the function (thus freezing the start time). Once the deferred function is running, all we need to do is show the difference in start time and current time.
We can use the net/http package to find the content type, or mime type, of a file. To do this, we open the file and read the first 512 bytes (as the DetectContentType() function only uses the first 512 bytes, there’s no point in doing more than needed). This function will then return a mime type, like application/json or image/jpg for instance.
When running a Go program in the terminal, your program could receive a signal interrupt from the OS for any number of reasons. One of which is if the user presses Ctrl+C on their keyboard (or whatever your operating system/terminal is set to). We can execute some code when this interrupt is received, mainly to clean up and reset what we were working on. In our example we use a goroutine to listen for the interrupt from signal.
We’ve already covered basic downloading of files - this post goes beyond that to create a more complete downloader by including progress reporting of the download. This means if you’re pulling down large files you are able to see how the download’s going. In our basic example we pass the response body into io.Copy() but if we use a TeeReader we can pass our counter to keep track of the progress.