LEARN GOLANG| Part-5
In case you are landing here directly, it’s suggested that you go and read through this for fundamentals.
In this blog, we shall be looking at following concepts :-
- Error Handling while dealing with Files in Go.
- Beautifying the error stack-trace.
- How to signal errors in Go.
- Demonstrating the use of Panic with examples in Go.
- Recovering from errors in Go.
- Go-Routines in Go.
- Sequential code-flow in Go.
- Building concurrency with GoRoutines.
- Demonstrating WaitGroup in Go.
- Communication between GoRoutines using Channels.
Question:- Demonstrate the process of Reading a File in GO program ?
Step #1.) These are the packages, that we have imported into our program :-
Step #2.) This is the configuration, to which we shall be reading the file :-
Step #3.) This is the file, that we would be reading into above configuration file :-
Step #4.) Here is the code to read the file from the given path :
Step #5.) Here is the code to start testing the file (here the file is well present with us @ the mentioned location @ line #30) :-
Step #6.) Now, let’s try to read a file, which is not present @ the mentioned location @ line #29. We are expecting an error as shown in output section below :-
Step #7.) Now, let’s try to read a file, which is not present @ the mentioned location @ line #29.
- We got an error in output as shown above. Also we got exitCode of 1, which is good.
- But we’re missing the context of why you wanted to open the file and where it happened. In languages, such as Python or Java, you’d use exceptions which will show you the stack trace where the problem was. To help us with this, Dave Cheney wrote a package called pkg/errors.
Question:- How can we beautify the error and view them more beautifully in GO program ?
Step #1.) We can make use of Go tool called pkg/errors. So, let’s first go ahead and install the same :-
Step #2.) Next, let’s import the same package to our codebase. Note that, we are importing two important packages here : “log” & “github.com/pkg/errors” :-
Step #3.) Next, let’s wrap-up the error with some beautified code-line and then return :-
Step #4.) Next, let’s setup the logging and invoke the same :-
Step #5.) Now, we can verify the above code-piece, by executing and we observe that, proper error message is also displayed in the terminal :-
Step #6.) Let’s also verify the logs formed into the “app.log” file for above invocation. Note that, entire stack-trace is being shown into the log-file :-
Question:- How can we signal the Errors in Go ?
Answer:- The usual method in Go for signalling errors is to return an error value. However, there are cases when there’s an error you can’t handle, and would like to signal this. In Go, there’s a built-in panic function that will do just that.
Question:- Let’s demonstrate with a simple example, the use of panic.
Answer:- In the below example, at line #10, we are trying to access the Index, which doesn’t exists and therefore, it shall cause the PANIC and abruptly end the program.
Question:- Can panic occur in the cases of Files as well ?
Answer:- In the below example, at line #12, we are trying to open a particular file, which doesn’t exists actually. This would lead to the panic situation once again :-
Question:- How can we recover from the Error situation ?
Answer:- In the below example :-
- At line #16, we have a “recover” function which is an anonymous function, being executed in defer mode. This function would help us to recover safely from the panic situation.
- Note that, as soon as the business of function “safeValue()” is finished, the anonymous recover function, shall be executed.
- Observe that, post line #9, statements are executed perfectly fine and the flow of the program is not being disturbed.
Question:- Demonstrate the full usecase of reading a file and converting the data to integer format ?
Answer:- In the below example, we shall be simulating the behaviour of reading a file, converting the data (thus read) into integer format and then killing the same :-
Step #1.) Let’s import the following packages to out codebase :-
Step #2.) Let’s now go ahead and perform following steps :-
- Reading a file and return, in case file can’t be opened.
- Next, we remove this file, that we just read.
- Next, we convert the data from string format to Integer format using “Atoi” function.
Step #3.) Let’s now create a file :-
Step #4.) Let’s now run the program and observe the behaviour :-
Note that, the file “server.pid” has been deleted well, post program execution.
Question:- Demonstrate the sequential access to multiple URLs through Go ?
Answer:- In the below example, you’d like to query a bunch of URLs, and see whether they return HTML, JSON, XML, or other format. You’ll do it by looking into the content type http header in the response. So we have our function, findReturnTypeOfUrl, which does an http call, and then, looks at the header and prints it out.
Question:- How much time has been taken by the above program ?
Answer:- We can see that it took about 7.050 seconds, to execute. Because we are blocked on every site, this is a very promising kind of data for concurrency.
Question:- Let’s implement concurrency in above situation ?
Answer:- Go’s concurrency primitive is a go routine. It’s very lightweight, and unlike processes or threads, you can spin tens of thousands of go routines on a single machine.
Question:- How do we generate the Go-Routines ? Can you show example ?
Answer:- Following is the way to generate the simple go-routines :-
- We are going to use the Go keyword, to generate a go routines, and create an anonymous function.
- The go run time will NOT wait for go routines that are still working. You can do a sleep to wait for them, but this is a very bad form of synchronisation. The same is reflecting well, in the output as well. No output is getting printed here.
Question:- What’s the correct way of brining the Synchronisation to the Go Routines ?
Answer:- There are usually 2 approaches for bringing in Synchronisation while using GO :-
- Go has the sync package with a bunch of utilities synchronised between go routines, but the recommended way is to use channels.
- You can use WaitGroup, which is exactly for waiting for a bunch of go routines to finish.
Question:- Can you explain in details, about the WaitGroup ?
Answer:- Following are the steps required to be done :-
Step #1.) We are going to import sync, and then in our main, we are going to create a WaitGroup.
Step #2.) Then for every go routine that we are going to spin, so we are going to tell the WaitGroup that we added another worker, and inside the go routine, we are going to signal that we are done. And lastly we are going to wait for all the go routines to be finished.
Step #3.) We can verify from above output that, total time taken now is ~3.78 seconds as compared to the ~7.05 seconds earlier (when the method was synchronous).
Question:- How does Go-Routines communicates amongst themselves ?
Answer:- The preferred way to communicate between go routines is by using channels.
That’s all in this section. If you liked reading this blog, kindly do press on clap button multiple times, to indicate your appreciation. We would see you in next series.