golang lambda_Golang Fantasy Hunting App,1:在AWS上将Golang应用程序部署到Lambda

golang lambda

Sometimes I get this weird urge not to self-flagellate. When that happens, I stop fucking around with Java, Javascript or Python and I turn to Go. Go is fast, light-weight and statically typed. Its package management system is a dream. You can get started with Go in about three seconds, which is 2 million times faster than the time it takes to work out what Microsoft was thinking when they created Typescript.

有时我得到这种奇怪的冲动,不要自我鞭打。 当发生这种情况时,我不再使用Java,Javascript或Python,而转向Go。 Go是一种快速,轻巧和静态输入的程序。 它的包裹管理系统是一个梦想。 您可以在三秒钟内开始使用Go,这比计算Microsoft创建Typescript时所考虑的时间要快200万倍。

This is the first in a series of articles where we’ll write and deploy an entire backend using Golang, DynamoDB, AWS Lambda and API Gateway. My intent is to show you just how much better it is to write backends in Go. If I am successful in convincing you, then this will have been a worthwhile process. If I’m not, it’s still worthwhile, because then you’ll have learned that you hate yourself and you can seek out professional assistance.

这是系列文章中的第一篇,我们将使用Golang,DynamoDB,AWS Lambda和API Gateway编写和部署整个后端。 我的目的是向您展示在Go中编写后端要好得多。 如果成功地说服你,那么这将是一个有价值的过程。 如果不是,那还是值得的,因为那样您就会了解到自己讨厌自己,可以寻求专业帮助。

我们将建立什么 (What we will build)

Eventually, the backend for a fantasy hunting log app where you can add new monsters, view all entries, and record kills.

最终,这是一个幻想狩猎日志应用程序的后端,您可以在其中添加新的怪物,查看所有条目并记录杀死事件。

In this specific article, we will create the first lambda (save-and-update) without any dynamo integration, deploy it to AWS and prove it works.

在这篇特定的文章中,我们将创建第一个lambda(保存并更新)而不进行任何dynamo集成,将其部署到AWS并证明其有效。

你需要什么 (What you need)

Go. I couldn’t explain the installation process any better than the official docs, so check those out here.

走。 我无法比官方文档更好地解释安装过程,因此请在此处查看

You also need an AWS account and some sort of code editor (I use VSCode).

您还需要一个AWS账户和某种代码编辑器(我使用VSCode)。

创建Lambda (Creating the Lambda)

Before we do any coding, we need to create a lambda in AWS. Go to the lambda console (here) and click ‘Create function’. Enter a name for your function and make sure you select Go 1.x from the runtime dropdown.

在进行任何编码之前,我们需要在AWS中创建一个lambda。 转到lambda控制台( 在此处 ),然后单击“创建功能”。 输入函数的名称,并确保从运行时下拉列表中选择Go 1.x

Image for post

Leave everything else the way it is and click ‘Create function’ at the bottom. Once created, scroll down to the ‘Basic Settings’ window and hit ‘Edit’.

保留一切,然后单击底部的“创建功能”。 创建完成后,向下滚动到“基本设置”窗口,然后点击“编辑”。

Image for post

Change the ‘handler’ from hello to main since our file is called main.go.

因为我们的文件名为main.go所以将“ handler”从hello更改为main

Save that, and that’s it for now.

保存,仅此而已。

Writing the Code

编写代码

To start, we’ll create a lambda that receives an HTTP request with our monster as the JSON payload. Then we will convert that JSON into our monster type and return only the name. If we get these three things working first then we can focus on dynamo without worrying about bugs elsewhere in the program.

首先,我们将创建一个lambda来接收一个以monster作为JSON负载的HTTP请求。 然后,我们将该JSON转换为我们的Monster类型,并仅返回名称。 如果我们首先使这三样东西起作用,那么我们就可以专注于发电机,而不必担心程序中其他地方的错误。

Assuming you’ve installed Go already, create a directory somewhere on your computer called fantasy-hunt and cd into it. Then, create a folder called save-and-update.

假设您已经安装了Go,请在计算机上的某个位置创建一个名为fantasy-hunt ,并将其插入cd 。 然后,创建一个名为save-and-update的文件夹。

This directory will contain a main.go file, which is where we’ll write the main entry point code for our save-and-update lambda. Later we will have a get-all lambda which will have its own main.go file.

该目录将包含一个main.go文件,在该文件中,我们将为save-and-update lambda编写主入口点代码。 稍后,我们将有一个get-all的λ,这将有自己的main.go文件。

Types

种类

Before we start writing any main code, though, I usually like to define the types our program will use. Designing strong data types is the best way to speed up development and avoid runtime bugs. Data is everything. Without it, there’s not much point in programming.

但是,在开始编写任何主要代码之前,我通常希望定义程序将使用的类型。 设计强大的数据类型是加快开发速度并避免运行时错误的最佳方法。 数据就是一切。 没有它,编程就没有多大意义。

Our program will only have one type: monster. Create a types folder in your fantasy-hunt directory, and then create a monster.go file inside it, which should look something like this.

我们的程序只有一种类型: monster 。 在fantasy-hunt目录中创建一个types文件夹,然后在其中创建一个monster.go文件,该文件应如下所示。

package types


type Monster struct {
	ID string `json:"id"`
	Name string `json:"name"`
	Hunted bool `json:"hunted"`
}

This is how you define a complex type in Go, which are somewhat like classes in other languages, but are called structs in Go. This one is a struct called Monster, which has three properties: ID, Name and Hunted.

这就是您在Go中定义复杂类型的方式,这种类型有点像其他语言中的类,但是在Go中称为structs 。 这是一个名为Monster的结构,它具有三个属性:ID,Name和Hunted。

Each of these properties is made up of three things, a name, a type and a string for mapping the object to json. The name and type sections are hopefully self-explanatory. The json part, i.e. `json:”id”` tells Go’s json library which part of a json payload that field should map to. So, for example, if we attempted to convert a json payload into a monster object, the json library would read each of these and workout that the id field in the json corresponds to the Id field of the struct, and so on.

这些属性中的每一个都由三部分组成:名称,类型和用于将对象映射到json的字符串。 名称和类型部分希望是不言自明的。 json部分,即`json:”id”`告诉Go的json库该字段应映射到json负载的哪一部分。 因此,例如,如果我们尝试将json有效负载转换为怪物对象,则json库将读取其中的每个内容,并进行锻炼,使json中的id字段对应于该结构的Id字段,依此类推。

You’ve probably noticed that the struct name and all the property names are capitalised. This is important. In Go, access to fields, objects and methods is controlled through capitalisation. If any of these names start with a capital letter, it means it is accessible outside of the immediate file where it is defined. If it starts with a lowercase letter, it isn’t. So here, because Monster and all of its properties are capitalised, it means we can reference this type from another file and still access everything on it. The json library also depends on the capitalisation, because it has to access the fields on the struct when marshaling (we will see marshaling in a second).

您可能已经注意到结构名称和所有属性名称都大写。 这个很重要。 在Go中,通过大写控制对字段,对象和方法的访问。 如果这些名称中的任何一个以大写字母开头,则意味着可以在定义它的直接文件之外访问它。 如果以小写字母开头,则不是。 所以在这里,因为Monster及其所有属性都大写,这意味着我们可以从另一个文件中引用此类型,并且仍然可以访问其中的所有内容。 json库还取决于大小写,因为封送处理时必须访问结构上的字段(我们将在第二秒看到封送处理)。

The last thing is the package declaration at the top. This simply defines a sort of namespace for the code. Since it’s in the types folder, we just call it types.

最后一件事是顶部的包声明。 这只是为代码定义了一种名称空间。 由于它位于types文件夹中,因此我们将其称为类型。

The main file

主文件

The main file is a little more complicated, so we will take it line by line.

主文件稍微复杂一点,因此我们将逐行介绍它。

package main


import (
	"github.com/aws/aws-lambda-go/lambda"
	"github.com/aws/aws-lambda-go/events"
	"net/http"
	"encoding/json"
	"../types"
)




func main() {
	lambda.Start(Handler)
}




func Handler(req events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	var monster types.Monster


	err := json.Unmarshal([]byte(req.Body), &monster)


	if err != nil {
		return response("Couldn't unmarshal json into monster struct", http.StatusBadRequest), nil
	}


	return response(monster.Name, http.StatusOK), nil
}


func response(body string, statusCode int) events.APIGatewayProxyResponse {
	return events.APIGatewayProxyResponse {
		StatusCode: statusCode,
		Body: string(body),
		Headers: map[string]string {
			"Access-Control-Allow-Origin": "*",
		},
	}
}
  • Line 1

    1号线

Another package declaration. Because this is the main file, we will call the package main, even though the folder is called save-and-update.

另一个包声明。 因为这是主文件,所以即使文件夹称为save-and-update ,我们也将其称为包main。

  • Lines 3–9

    第3–9行

Import statements. Go’s package management system lets you directly pull github repo’s and use them in your code. That’s what we do here for the AWS lambda and events packages. Once you’ve defined them in your code, you have to run go get <github-url> in your terminal to download them to your machine, e.g. go get github.com/aws/aws-lambda-go/lambda

导入语句。 Go的包管理系统使您可以直接拉github repo并将其用于代码中。 这就是我们在这里为AWS lambda和事件包所做的。 一旦在代码中定义了它们,就必须在终端中运行go get <github-url>以将它们下载到您的机器上,例如go get github.com/aws/aws-lambda-go/lambda

The non-github imports don’t require you to install anything. The ones on line 6 & 7 are from the Go standard library which comes pre-installed with Go. We use net/http to access all the HTTP StatusCode constants. We use encoding/json to parse and convert JSON into our struct types.

非github导入不需要您安装任何东西。 第6和7行上的代码来自Go预先安装的Go标准库。 我们使用net/http访问所有HTTP StatusCode常量。 我们使用encoding/json进行解析并将JSON转换为我们的结构类型。

Line 8 imports our types package.

第8行导入我们的类型包。

  • Lines 12–14

    第12-14行

Every main Go package needs a main function. This is the function that is called when we run a Go program. This one only calls lambda.Start(Handler) which tells AWS that our Handler function (what we will see next) is what should be called when the lambda gets called.

每个主要的Go软件包都需要一个主要功能。 这是我们运行Go程序时调用的函数。 这个仅调用lambda.Start(Handler) ,它告诉AWS当调用lambda时应调用我们的Handler函数(接下来将要看到的内容)。

  • Line 17

    17号线

This is our Handler function declaration. It receives one parameter, req of type ApiGatewayProxyRequest from the events package. We use this type because we’ll be integrating with API Gateway later. It returns two things; a variable of type ApiGatewayProxyResponse and an error. This is a common pattern in Go. Functions will often return the actual value and an error value, and if the error value is not nil (like null in other languages) then we can assume that the function has failed somewhere. We’ll see that used in a second.

这是我们的Handler函数声明。 它从events包中接收一个参数,即ApiGatewayProxyRequest类型的req 。 我们使用此类型,因为稍后将与API Gateway集成。 它返回件事; 类型为ApiGatewayProxyResponse的变量和错误。 这是Go中的常见模式。 函数通常会返回实际值和错误值,如果错误值不为nil (如其他语言中的null),那么我们可以假定函数在某处发生了故障。 我们将在一秒钟内看到它。

  • Line 18

    18号线

We create a variable of type Monster.

我们创建一个Monster类型的变量。

  • Line 20

    20号线

This is where we convert the JSON payload to our monster type, which is what Unmarshal does. The first parameter has to be a byte array, so we convert the Body field of our req parameter to a byte array by calling []byte(req.Body). The second parameter is the monster object we created.

这是我们将JSON有效负载转换为我们的怪物类型的地方,这正是Unmarshal所做的。 第一个参数必须是字节数组,因此我们可以通过调用[]byte(req.Body)req参数的Body字段转换为字节数组。 第二个参数是我们创建的怪物对象。

The & symbol here tells Go that we want to pass our monster object by reference. This means that any changes that get made to the monster object inside the Unmarshal function should also get made to the monster object we have in our Handler function, i.e., when Unmarshal is finished doing its thing, our monster field will be filled in without having to explicitly return it.

这里的&符号告诉Go我们想通过引用传递怪物对象。 这意味着对Unmarshal函数中的Unmarshal对象所做的任何更改也应该对我们在Handler函数中具有的Monster对象进行更改,即,当Unmarshal完成其工作时,我们的Monster域将被填充而无需明确返回它。

The Unmarshal function could return an error, so that’s why we’re putting the result of it into an err object. We use the special := operator, which effectively tells Go to create the object, work out the type on its own and then fill it in, all at the same time, without us having to explicitly do that.

Unmarshal函数可能返回错误,因此这就是我们将其结果放入err对象的原因。 我们使用特殊的:=运算符,该运算符有效地告诉Go创建对象,自行计算类型,然后同时填充它,而无需我们显式地进行操作。

  • Lines 22–24

    22-24行

This is typically how error handling is done in Go. If no error occurred during the Unmarshal function, err would be nil, which means the if statement would not execute. If it does execute, it returns the result of calling our response function, which we will look at in a second. We also have to specify , nil at the end of this line, because this function is supposed to return 2 things, but we’re handling the error gracefully so we can just make the err object nil.

这通常是Go中错误处理的方式。 如果在Unmarshal函数执行过程中未发生任何错误,则err将为nil ,这意味着if语句将不会执行。 如果确实执行,它将返回调用我们的response函数的结果,我们将在稍后查看。 我们还必须在此行的末尾指定, nil ,因为该函数应该返回2个东西,但是我们正在优雅地处理错误,因此我们可以将err对象设置为nil。

  • Line 26

    26号线

This calls the response function and passes it our monster’s name and the http OK status code, because by this point we’ve successfully finished what we wanted to do.

这将调用响应函数并将其传递给我们的怪物名称和http OK状态代码,因为到此为止,我们已经成功完成了我们想做的事情。

  • Lines 29–37

    第29–37行

Here we are creating a function which takes in a body and a status code and then returns the type of value that amazon lambda expects us to return, an events.ApiGatewayProxyResponse. Then it returns it, filling in the status code, the body, and a map of headers for CORS purposes.

在这里,我们正在创建一个函数,该函数接受主体和状态码,然后返回amazon lambda期望我们返回的值的类型,即events.ApiGatewayProxyResponse 。 然后返回它,并出于CORS的目的填写状态代码,正文和标头映射。

Uploading the Lambda to AWS

将Lambda上载到AWS

Now that the code is completed, we can build and deploy our lambda. The first step to this is compiling our code into a linux binary (aws lambda requires this).

现在代码已完成,我们可以构建和部署lambda。 第一步是将我们的代码编译成linux二进制文件(aws lambda要求这样做)。

In your terminal, navigate to your save-and-update folder and run the following command:

在您的终端中,导航到“ save-and-update文件夹并运行以下命令:

GOOS=linux GOARCH=amd64 go build -v main.go

GOOS=linux GOARCH=amd64 go build -v main.go

This should spit out a binary file into the folder called main.

这应该将二进制文件吐出到名为main的文件夹中。

Using your GUI, find that file and zip it up into an archive called main.zip. Then navigate back to your lambda’s console and find the Function code section. Select the Actions dropdown and choose Upload a .zip file.

使用您的GUI,找到该文件并将其压缩到名为main.zip的存档中。 然后导航回lambda的控制台并找到“ Function code部分。 选择“ Actions下拉列表,然后选择“上Upload a .zip file

Image for post

Find your main.zip archive and upload it.

找到您的main.zip存档并上传。

Once that’s complete, we can test that the lambda is working as expected. Find the Test button at the top of the page. It should open a modal where you can configure a test event. Find the Event template dropdown and search for Amazon API Gateway AWS Proxy. This is the type of event that will be sent to your lambda when it’s called from an API Gateway.

完成后,我们可以测试lambda是否按预期工作。 找到页面顶部的“ Test按钮。 它应该打开一个模式,您可以在其中配置测试事件。 查找事件模板下拉列表,然后搜索Amazon API Gateway AWS Proxy 。 这是从API网关调用时将发送到您的lambda的事件类型。

The event payload should now be filled in. Find the body property at the top and edit it so that you’re passing in this:

现在应该填写事件有效负载。在顶部找到body属性,然后对其进行编辑,以使您能够通过此操作:

"{ \"id\": \"1\", \"name\": \"A Scary Monster\", \"hunted\":true }"

This is what our monster JSON payload looks like. Give your test event a name and save it.

这就是我们的怪物JSON有效负载。 给您的测试事件命名并保存。

Now, if you hit the Test button, your lambda should execute, and you should see a response like this:

现在,如果您单击“ Test按钮,则应执行lambda,并应看到如下所示的响应:

{
"statusCode": 200,
"headers": {
"Access-Control-Allow-Origin": "*"
},
"multiValueHeaders": null,
"body": "A Scary Monster"
}

And that’s it.

就是这样。

There’s still a bit to be done before this app can be used by fantasy hunters, but hopefully you’ve had a nice taster of Go and it’s made you hungry for more. So far, you’ve learned about packages, structs, functions, multiple returns, error handling, compiling and deploying to AWS. With that grounding, we can begin to get into more complex stuff. But it actually never really gets too complicated, because Go is great. Go loves you. You should love it back.

幻想猎人可以使用这个程序之前,还有很多工作要做,但是希望您对Go有了一个很好的品尝,并且让您渴望更多。 到目前为止,您已经了解了包,结构,函数,多次返回,错误处理,编译和部署到AWS。 基于此基础,我们可以开始研究更复杂的内容。 但是实际上它从来不会变得复杂,因为Go很棒。 去爱你。 你应该爱它。

You can find all the code for this article in this repo.

您可以在此 仓库中 找到本文的所有代码

翻译自: https://levelup.gitconnected.com/golang-fantasy-hunting-app-1-deploying-a-golang-app-to-lambda-on-aws-f9b950648bae

golang lambda

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值