Basics of Go

Response & Error Handling

Maximiliano Firtman

Maximiliano Firtman

Independent Consultant
Basics of Go

Check out a free preview of the full Basics of Go course

The "Response & Error Handling" Lesson is part of the full, Basics of Go course featured in this preview video. Here's what you'd learn in this lesson:

Maximiliano showcases the creation of response and error handlers using the built-in HTTP status codes provided by the Go http package. These handlers are useful for managing and handling various HTTP responses and errors in a Go application.


Transcript from the "Response & Error Handling" Lesson

>> So, it's complaining because we are not using the response or the error object. We know how that works. Well, first let's start with if there is any error. So if we do have an error, it means that the error is not nil. What should we do? Actually, what we need to do is to follow the same pattern back.

So because we are a function, it's responsibility is to get the rate. It shouldn't decide what to do in the UI in case there is an error. So we are splitting responsibility. My responsibility ends on getting the rate from a JSON and that's all. So if I cannot do that, I should pass that back to the caller.

I cannot do that. So maybe you can just return no rate and the same error that we have received. The problem that we have, remember I mentioned I will make a small change here is that I cannot return nil because if I say that I need a rate it's expecting me to return a rate and you can say well, how can I respond with an empty rate?

That that's like crazy new empty right, I can do that but if you actually like to send nil you actually need to change the rate how you just send a pointer to a rate. And a pointer can be nil. So in this case, the pointer, remember, is just a memory address of another variable, another object, another instance.

So that's why typically, you will see that's why when you get into the Get specification, they also have the after there, the star. So every time you are following this pattern and you are returning structures, typically you use the star so you can return nil, okay? That's just that not the big deal anyway.

Okay, so if not, well, I don't need the else because we are returning anyway. This is just how you like to see if else is, anyway, it seems like we are ready to continue, right? So, we have a response. Okay, makes sense? So, first, if we have a response, it means that the server has just answer with something, but maybe it's not the answer we're looking for.

When we are using htpp, for example, maybe it's an 404, it means that it doesn't, what you're looking for is not there, or maybe the service is not working properly and it's giving error 500. So in those cases, I should check first if the status code of the response is the one that I like.

Do you know which is the number for everything is okay? It's 200. You can use the number or we do have constants within the HTTP package representing all the possible, but not all the possible most of the possible http status codes, so I can say http status. Okay, do we have all of them?

We have most of them but HTTP codes are changing with time. So for example, now we have a new one called 103. It's called early hints that I think it's not there, and then the list of constants that is for performance and also we have another one, that is 451.

That I think it's not there, so 451. Let's go. This one is unavailable for legal reasons. Does anyone know why they're using this number 451? Fahrenheit 451, what is that? It's too hot I know. It's a book from Ray Bradbury where they were, actually, I think it's the point on where paper burns.

Because they were burning books there. So the idea is that the government is burning websites
>> [LAUGH]
>> And that's kind of the idea. Okay, so, well, that status code is not in the constant, but you can still use a number anyway, okay? 418 HTTP status code. I'm a teapot.

No one gets, okay, what's that? Yeah, because it's permanently a teapot. Yeah, someone thought that was funny. Anyway, do we have, maybe we can check. Do we have a status teapot? I'm a teapot? I don't think so. No teapot, StatusTeapot. Yeah, we have it, yeah we have it, we have a concept for teapot.

Cool. Well, okay, it's fine for us. So that means that yeah, we should have the result here. Where is the result? We do have a body. The first problem that we have is the body is not what we are expecting. It's not a string, and we are talking the type.

It's not even bytes, it's a read closer. I don't know what that is, but it has to do with working with strings. I'm not sure if you have experience working with strings. In this case, it's because actually http works over TCP or UDP, it doesn't matter, but actually you are getting not the whole response at once.

The TCP stack is giving you the response in chunks as soon as they are available from the network. That's why it's a progressive download. So you can actually stream that here as well. So you can receive chunks of the JSON response and maybe partially analyze them or something like that.

It's a lot of work. You need to have a real use case for that. Most of the time, we wanna have the whole thing. So we wanna wait for the whole thing. So to do that, we can do it manually. So we can read byte by byte until it gets to the end.

So there is an end of file. There is a signal saying, okay, we are done, we don't have any more bytes here in this buffer. But we do have an IO package. Where we have input output tools such as read all. Read all will receive a reader with a stream and it will read everything until the end, synchronously in one execution.

So that means that the thread will be there Helder until the sun. But we know that if you wanna get over that we have Go routines, and we will get there later. But I mean that the thread will wait there. So this is like in JavaScript having an await.

It will be there waiting for the response and read all returns on a slice of bytes or error. So we are still using the same technique here. So we have, let's say we can call these data or bodyBytes and we have another error like so. Can I reuse err as a bio name?

How do you think?
>> It's in a new blocks.
>> It's in a new block. So actually, I can do this, so I can create a new one but having mine now I won't have access to the other one to the outer one within that if maybe that's okay.

In this case it's okay because I already past that moment. So I'm not going back to that error, okay but have that in mind. So in this case we have device, okay, so we can try to where we can say if another if we don't have an error, if we do have an error, we're actually going to again return or error.

Maybe, what's a possible error here? Well, maybe the connection was closed, so the server was responding, but for some reason the connection closed. I mean, your connection, your Wi-Fi is off, just in the middle of the connection or the server is down, or something happened, or you have a firewall.

Something happened that actually stopped the flow of bytes before ending. And that's kind of the possibility. And then we have the bodyBytes in and a slice of bytes, we can get it as a string if we want to. As a JSON string just by calling the string converter.

It receives the bytes and it will convert that into a string using UTF eight. So just to see if this is working, we can just print this for debugging purposes. So we can print that JSON. Okay. Well, before even trying to test this, there is an error here at the end of the function because I'm not returning a rate, okay?

Because I should return a rate. So I, before continuing this, by the way, I need to also put analysis here in case the status code is not okay, make sense? So, let's finish at least this part so, we can see if something is working. What we can do here?

I need to return another error, okay? Like this. So, this is a network error, or the domain doesn't work, the URL is down, the URL is wrong, this is okay, was okay. The headers were okay but when we tried to get the body, something happened. And now we have the server respond with a non 200 response.

So in this case, we need to do something similar. But the problem is that I'm not sure if you spot the problem. If we just return nil, so no response and error, the problem is that this error will actually be this one. That is actually nil, because we actually had a response, not the one that we were expecting but we do have a response.

So in this case, we are returning nil, nil. So the color will never know what happened here, which of the two options do you wanna use? So because we don't have actually an error option, an error instance, when the server responded with a 404, we need to create one.

So we need to create a response, an error. How to create an error. Well, to create an error, there is an errors package. And the errors package, you can create a new error. However, most of the time, we use the format package that has an error f function.

So every time you see an F suffix, it has to do with format. The format string. Okay, so typically you can create a new error with this string saying, for example, status code received. And then you say, I wanna put here a value, it can be also a digit, and then you pass the status code.

So it's like you're creating your own error messages. Okay, so now finally, after the last else, we can return what? Our object, so we actually need to return. All right, so we need to agree to rate remember our idea was to create the rate option. So, we create the rate, we say, rate, how to create an object from an A structure an instance that's actually the right name is instance, I'm creating an instance of an object.

Data types the rate and then we can use the constructor. Remember, structures have constructors, so I can set the currency is coming from the string that I have here. So I have the currency. That's the first argument from the argument and the second value is the price, and I should get the price from somewhere.

I didn't pass the JSON yet, so for now let's say 20, just to see if something's working. And I will try to return the rate. But if I try to return the rate, it doesn't work. Do you know why? By the way first I should return rate and nil, nil forever okay.

So because I always need to return to elements, okay, but still the rate complaints. What's the problem? What's the type of my return?
>> Pointer?
>> A pointer. And the rate is not the pointer, it's the actual rate. How do I get a pointer of an instance of a variable?

The ampersand. And also, I need to use here colon equals, because it's not actually a variable. Or you add bar. That's a prefix. It is the same, but you need one or the other. O bar or colon equals. Okay? We are still not parsing the trace and getting the value from it, okay?

But also, I have a warning here. So if you look what the warning says, look at that error a string shouldn't be capitalized. Why? I don't know. If you ask me that's a weird reason. But they asked me not to capitalize the, I'm talking about the error message.

He says, can you just use lowercase s for the error message. I don't know the reason. Maybe there is a reason why, but it works. But they like, I mean, Go likes all error messages in lowercase. It's a string at the end, right? But anyway.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now