Build Go Apps That Scale on AWS

Creating a Serverless Function



Build Go Apps That Scale on AWS

Check out a free preview of the full Build Go Apps That Scale on AWS course

The "Creating a Serverless Function" Lesson is part of the full, Build Go Apps That Scale on AWS course featured in this preview video. Here's what you'd learn in this lesson:

Melkey creates a serverless function in the lambda package in the application. It receives an event and returns either a string or an error depending on whether a username exists on the event.


Transcript from the "Creating a Serverless Function" Lesson

>> So here in our main.go, we actually have to pull in some packages. So there's gonna be the first time we're not gonna depend just on the standard library. We have to depend on the Go AWS SDK, okay? So first, I want to type You can see that we have that package added, okay?

And like I said, all Lambda does is it handles a function for us. So we're gonna to define that function. So what I'm gonna do here, is I'm gonna create a new function called func HandleRequest, okay? Let's just give it that bare bone skeleton for any Go function.

And what this function is going to do is, it's going to take in a payload, right? And do something with it, okay? Let's just keep it simple, right? KISS, and so the first thing I wanna define is a struct, because that struct is going to be the data that our payload is gonna come in.

So we're gonna do type, let's just say it's gonna be called my event. It's gonna be a struct, and if you think about this, the only, like right now, the only field I care about is a field called username. Let's create a username field. It's gonna be a string, okay?

And there's something I did not mention earlier when I talked about structs. Structs in Go have an additional option to tag it, okay? Tagging is a way for Go and other libraries to really handle data into your struct. A very popular example of tagging is using the JSON tags.

So we can do backtick JSON, and then we can put username. So, what is this? What did we just do? Basically, when we get a JSON payload or JSON request from our client, typically it's JSON, right? It's gonna have a username and then whatever the value of that username is.

So, mine's gonna be Melky. With this ability, we can actually unmarshal that raw request, that raw HTTP request we're getting from our client into this struct with one line of code. And now we have abilities to handle everything in that payload from our client with our struct. We call methods on it, we can just take that field, take that attribute, do whatever you want with this property now.

So we have the Tunnel Request. What I'm gonna do is this handle request is gonna take my event type. So it's gonna be event, my event. So we know what we're gonna expect to call with our function, what our Lambda is gonna expect to do with this function, I should say.

And then here, let's do some basic logic. We'll say if event.username is empty, right? Basically what I wanna do here is return an error, something happened from our client that we did not expect, and with Go, we need to also tell it what is gonna be return type.

What is the expected return type of our function here? For right now, we just need an error. An error is a native type in Go. These are individual types, and one core thing about Go, and I have not talked about this yet, errors, our values in Go. There's no real try-catch exceptions nothing like that.

You treat an error as if you treat any other value from the values you've handled with structs anything from like a for loop that value you handle it the exact same way. What does this mean? One is your code is now fully in your control of how you handle these errors, right?

If there's an error that you did not suspect, you have to kinda handle that code, maybe bubble it up back to the caller, but say, hey, we experienced this error, here you go. It's an error type or maybe there's an unforeseen behavior in your code and it's dangerous.

Well, now we wanna panic. We wanna just completely this was not something that we had thought of this should never exist but it did we have to panic our application and basically run it down, okay? But there's also things you can do with errors that aren't so scary as panicking can gracefully handle it you can log it totally up to you in some cases like we showed before, you can just ignore it cuz errors are values.

Remember when we had the for loop and we didn't use like an index or a value, we just put underscore? You can do the exact same with an error. So it's dangerous, but it gives us as the software developer, software engineer, more control as to how our code is executed and how it's handled under certain situations.

Cool, so here, if the event.Username is empty, what I'm gonna do is return. I'm gonna use our format package. I'm gonna create, basically, a new error type with error format. I'm gonna say, username cannot be empty, okay? And it's gonna get bubbled back up to our client, the caller.

And then here, what I'd like to do is, if it's not an error, and this is, again, a super basic example, we're gonna do return format.sprintf. And what sprintf does, different than printf or println, is it returns a value for us to use, okay? So then we have access to this new string.

We can use it accordingly. We can pass it down whatever we want. That's the difference between printf and sprintf, okay? Here, let's just do successfully called by, and let's add our format specifiers, so modulo s and we can do event.Username. Okay, and here we're actually going to do is modify this and not only be an error, but also a string so we can return multiple things from our Go code.

So I'm gonna do string error, and now we're gonna get to say, hey, there's not enough returns here. So in our first return, we're gonna return empty string, okay? So nothing successful. It's gonna run on the error that gets returned. And then down here, this can be the first return, and then the second one is nil.

Now, why is it nil? Does anyone have like a guess? The zero value of an error is a nil. So we can use nil to satisfy the error type constraint for our functions here. And you'll see this very commonly, right? If error does not equal to nil, we're gonna write a ton of that, don't worry.

But nil values are dangerous, but they're also useful in how you wanna orchestrate your code, right? And references, they also zero to a nil value. Which makes it contentiously maybe easier to handle some logic, but also, again, if you try to run a method on a nil, you're gonna get a panic and that's not something you can control, right?

In terms of if you can control a panic, you can literally write, if you get an error, we have the option just running panic and do whatever we want, right? Panic, no, this is really bad. We can do that. I don't want to. It seems I don't want to panic mentor application, I can handle it a different way.

I can just return to the caller, okay, this is an error there you go, maybe fix something on your end.

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