在SOFWARE开发生命周期(SDLC)的每个阶段,开发人员必须在数据库,授权,部署机制,服务器尺寸,存储管理等方面做出战略决策。这些决策必须进行彻底评估,因为它们可以显着影响开发过程参与构建应用程序。
一个范式开发人员不断拥抱是Backend-as-a-Service (BaaS)。 BAA摘要与SDLC相关的开发开销,并仅关注业务逻辑。它为开发人员提供了服务器端功能,例如用户身份验证,数据库管理,云存储等。
在这篇文章中,我们将通过在GO中构建项目管理API来探索AppWrite作为BAA的利用。 API将提供创建,阅读,更新和删除项目的功能。可以找到项目存储库here。
什么是AppWrite?
AppWrite是一个开源后端,作为一个服务平台,可为构建Web,移动和后端服务提供一组API和SDK。以下是在任何应用程序中使用AppWrite的一些好处:
- 提供可扩展且稳健的数据库
- 实时功能
- 支持无服务器功能
- 安全证书和加密
- 身份验证和授权机制
先决条件
要与本教程一起,需要以下内容:
- 对GO的基本理解
- AppWrite帐户。注册是free
入门
要开始,我们需要导航到所需的目录并运行以下命令:
cargo new go-appwrite && cd go-appwrite
此命令创建一个名为go-appwrite
的GO项目,并导航到项目目录。
接下来,我们需要通过运行以下命令来初始化一个GO模块来管理项目依赖项:
go mod init go-appwrite
此命令将创建一个用于跟踪项目依赖项的go.mod
文件。
最后,我们继续使用:
安装所需的依赖项
go get github.com/gin-gonic/gin github.com/go-playground/validator/v10 github.com/joho/godotenv
github.com/gin-gonic/gin
是构建Web应用程序的框架。
github.com/go-playground/validator/v10
是用于验证结构和字段的库。
github.com/joho/godotenv
是一个用于加载环境变量的库
构建我们的应用程序
必须拥有一个良好的项目结构,因为它使代码库可维护和无缝供任何人阅读或管理。为此,我们必须在项目目录中创建一个api
,cmd
和data
文件夹。
api
用于构建我们的API相关文件
cmd
用于构建我们的应用程序入口点
data
用于构建我们的应用程序数据
设置AppWrite
要开始,我们需要登录到我们的appwrite console,单击创建project 按钮,输入go_appwrite
作为名称,然后 create 。
创建数据库,集合并添加属性
appwrite船只可以在构建项目管理API方面使用可扩展且可靠的数据库。为此,首先,导航到数据库选项卡,单击创建数据库按钮,输入project
作为名称,然后 create 。。 P>
其次,我们需要创建一个用于存储项目的集合。为此,请单击创建集合按钮,输入project_collection
作为名称,然后单击创建。
最后,我们需要创建属性来表示我们的数据库字段。为此,我们需要导航到属性选项卡,并为下面显示的每个值创建属性:
属性键 | 属性类型 | 大小 | 必需 |
---|---|---|---|
名称 | 字符串 | 250 | 是 |
描述 | 字符串 | 5000 | 是 |
创建属性后,我们看到它们如下所示:
创建一个API键
要安全地连接到AppWrite,我们需要创建一个API密钥。为此,我们需要导航到概述选项卡,滚动到与服务器部分集成,然后单击 api键按钮。
接下来,输入api_go
作为名称,单击下一个按钮,选择数据库作为所需范围,然后 create 。
利用AppWrite在GO中构建项目管理API
通过在AppWrite上完全设置我们的项目,我们现在可以使用数据库而无需旋转任何服务器或管理任何其他技术开销。
设置环境变量
要安全地连接到我们的AppWrite Provisioned Server,AppWrite提供了一个端点和一组唯一ID,我们可以使用这些ID来执行所有必需的操作。要设置所需的环境变量,我们需要在根目录中创建一个.env
文件,然后添加下面的摘要:
API_KEY=<REPLACE WITH API KEY>
PROJECT_ID=<REPLACE WITH PROJECT ID>
DATABASE_ID=<REPLACE WITH DATABASE ID>
COLLECTION_ID=<REPLACE WITH COLLECTION ID>
我们可以从AppWrite控制台中获取所需的API键和ID,如下所示:
创建API模型
接下来,我们需要创建模型来表示我们的应用程序数据。为此,我们需要在data
文件夹中创建一个model.go
文件,然后添加下面的摘要:
package data
type Project struct {
Id string `json:"$id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
}
type ProjectRequest struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
}
type ProjectResponse struct {
Id string `json:"$id,omitempty"`
CollectionId string `json:"$collectionId,omitempty"`
}
type JsonAPIBody struct {
DocumentId string `json:"documentId,omitempty"`
Data *ProjectRequest `json:"data,omitempty"`
}
上面的摘要创建了Project
,ProjectRequest
,ProjectResponse
和JsonAPIBody
结构,并具有所需属性来描述请求和响应类型。
创建API路由
使用模型完全设置,我们需要导航到api
文件夹,并创建一个用于配置API路由的route.go
文件,并在下面添加摘要:
package api
import "github.com/gin-gonic/gin"
type Config struct {
Router *gin.Engine
}
func (app *Config) Routes() {
//routes will come here
}
上面的摘要执行以下操作:
- 导入所需的依赖项
- 使用
Router
属性创建一个Config
结构,以配置应用程序方法 - 创建一个
Routes
函数,该函数将Config
struct作为指针
创建API帮助者
通过完全设置应用程序模型,我们现在使用它们来创建我们的应用程序逻辑。为此,我们需要在API
文件夹中创建一个helper.go
文件,然后添加下面的摘要:
package api
import (
"log"
"net/http"
"os"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/joho/godotenv"
)
type jsonResponse struct {
Status int `json:"status"`
Message string `json:"message"`
Data any `json:"data"`
}
func GetEnvVariable(key string) string {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
return os.Getenv(key)
}
func (app *Config) validateJsonBody(c *gin.Context, data any) error {
var validate = validator.New()
//validate the request body
if err := c.BindJSON(&data); err != nil {
return err
}
//validate with the validator library
if err := validate.Struct(&data); err != nil {
return err
}
return nil
}
func (app *Config) writeJSON(c *gin.Context, status int, data any) {
c.JSON(status, jsonResponse{Status: status, Message: "success", Data: data})
}
func (app *Config) errorJSON(c *gin.Context, err error, status ...int) {
statusCode := http.StatusBadRequest
if len(status) > 0 {
statusCode = status[0]
}
c.JSON(statusCode, jsonResponse{Status: statusCode, Message: err.Error()})
}
上面的摘要执行以下操作:
- 导入所需的依赖项
- 创建一个
jsonResponse
结构来描述API响应 - 创建一个使用
godotenv
软件包加载和获取环境变量的GetEnvVariable
函数 - 创建一个
validateBody
函数,该函数将Config
struct作为指针作为指针并返回error
。在函数内部,我们验证请求data
的格式正确,还使用验证器库进行验证并检查所需的字段 - 创建一个
writeJSON
函数,该函数将Config
struct作为指针作为指针,并使用jsonResponse
struct构造API响应。 - 创建一个
errorJSON
函数,该函数将Config
struct作为指针作为指针,并在存在错误时使用jsonResponse
struct构造API响应
创建API服务
通过完全设置应用程序模型,我们现在使用它们来创建我们的应用程序逻辑。为此,我们需要创建一个service.go
文件,并通过以下内容进行更新:
首先,我们需要导入所需的依赖项,创建环境变量并创建用于创建项目的函数。
package api
import (
"bytes"
"encoding/json"
"fmt"
"go-appwrite/data"
"io/ioutil"
"net/http"
)
//get details from environment variable
var projectId = GetEnvVariable("PROJECT_ID")
var databaseId = GetEnvVariable("DATABASE_ID")
var collectionId = GetEnvVariable("COLLECTION_ID")
var apiKey = GetEnvVariable("PROJECT_ID")
func (app *Config) createProject(newProject *data.ProjectRequest) (*data.ProjectResponse, error) {
url := fmt.Sprintf("https://cloud.appwrite.io/v1/databases/%s/collections/%s/documents", databaseId, collectionId)
createdProject := data.ProjectResponse{}
jsonData := data.JsonAPIBody{
DocumentId: "unique()",
Data: newProject,
}
postBody, _ := json.Marshal(jsonData)
bodyData := bytes.NewBuffer(postBody)
//making the request
client := &http.Client{}
req, _ := http.NewRequest("POST", url, bodyData)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("X-Appwrite-Key", apiKey)
req.Header.Add("X-Appwrite-Project", projectId)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(body), &createdProject)
if err != nil {
return nil, err
}
return &createdProject, nil
}
上面的摘要执行以下操作:
- 导入所需的依赖项
- 创建所需的环境变量
- 创建一个
createProject
函数,该函数将Config
struct作为指针,并返回创建的项目详细信息或错误。这些函数还通过包括所需的环境变量,添加所需的标题并提出请求。
ps :创建项目时指定的unique()
标签告诉appwrite以自动化项目ID。
其次,我们需要添加一个使用与createProject
功能相似的逻辑来获取项目详细信息的getProject
函数。
//import goes here
func (app *Config) createProject(newProject *data.ProjectRequest) (*data.ProjectResponse, error) {
//createProject code goes here
}
func (app *Config) getProject(documentId string) (*data.Project, error) {
url := fmt.Sprintf("https://cloud.appwrite.io/v1/databases/%s/collections/%s/documents/%s", databaseId, collectionId, documentId)
projectDetail := data.Project{}
//making the request
client := &http.Client{}
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("X-Appwrite-Key", apiKey)
req.Header.Add("X-Appwrite-Project", projectId)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(body), &projectDetail)
if err != nil {
return nil, err
}
return &projectDetail, nil
}
第三,我们需要添加一个updateProject
功能,该功能使用与createProject
功能相似的逻辑来更新项目的详细信息。
//import goes here
func (app *Config) createProject(newProject *data.ProjectRequest) (*data.ProjectResponse, error) {
//createProject code goes here
}
func (app *Config) getProject(documentId string) (*data.Project, error) {
//getProject code goes here
}
func (app *Config) updateProject(updatedProject *data.ProjectRequest, documentId string) (*data.ProjectResponse, error) {
url := fmt.Sprintf("https://cloud.appwrite.io/v1/databases/%s/collections/%s/documents/%s", databaseId, collectionId, documentId)
updates := data.ProjectResponse{}
jsonData := data.JsonAPIBody{
Data: updatedProject,
}
postBody, _ := json.Marshal(jsonData)
bodyData := bytes.NewBuffer(postBody)
//making the request
client := &http.Client{}
req, _ := http.NewRequest("PATCH", url, bodyData)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("X-Appwrite-Key", apiKey)
req.Header.Add("X-Appwrite-Project", projectId)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(body), &updates)
if err != nil {
return nil, err
}
return &updates, nil
}
最后,我们需要添加一个使用与createProject
函数相似的逻辑来删除项目详细信息的deleteProject
函数。
//import goes here
func (app *Config) createProject(newProject *data.ProjectRequest) (*data.ProjectResponse, error) {
//createProject code goes here
}
func (app *Config) getProject(documentId string) (*data.Project, error) {
//getProject code goes here
}
func (app *Config) updateProject(updatedProject *data.ProjectRequest, documentId string) (*data.ProjectResponse, error) {
//updateProject code goes here
}
func (app *Config) deleteProject(documentId string) (string, error) {
url := fmt.Sprintf("https://cloud.appwrite.io/v1/databases/%s/collections/%s/documents/%s", databaseId, collectionId, documentId)
//making the request
client := &http.Client{}
req, _ := http.NewRequest("DELETE", url, nil)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("X-Appwrite-Key", apiKey)
req.Header.Add("X-Appwrite-Project", projectId)
resp, err := client.Do(req)
if err != nil {
return "", err
}
_, err = ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return documentId, nil
}
创建API处理程序
完成此操作,我们可以使用服务来创建API处理程序。为此,我们需要在api
文件夹中创建一个handler.go
文件,然后添加下面的摘要:
package api
import (
"context"
"fmt"
"go-appwrite/data"
"net/http"
"time"
"github.com/gin-gonic/gin"
)
const appTimeout = time.Second * 10
func (app *Config) createdProjectHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
_, cancel := context.WithTimeout(context.Background(), appTimeout)
var payload data.ProjectRequest
defer cancel()
app.validateJsonBody(ctx, &payload)
newProject := data.ProjectRequest{
Name: payload.Name,
Description: payload.Description,
}
data, err := app.createProject(&newProject)
if err != nil {
app.errorJSON(ctx, err)
return
}
app.writeJSON(ctx, http.StatusCreated, data)
}
}
func (app *Config) getProjectHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
_, cancel := context.WithTimeout(context.Background(), appTimeout)
projectId := ctx.Param("projectId")
defer cancel()
data, err := app.getProject(projectId)
if err != nil {
app.errorJSON(ctx, err)
return
}
app.writeJSON(ctx, http.StatusOK, data)
}
}
func (app *Config) updateProjectHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
_, cancel := context.WithTimeout(context.Background(), appTimeout)
projectId := ctx.Param("projectId")
var payload data.ProjectRequest
defer cancel()
app.validateJsonBody(ctx, &payload)
newProject := data.ProjectRequest{
Name: payload.Name,
Description: payload.Description,
}
data, err := app.updateProject(&newProject, projectId)
if err != nil {
app.errorJSON(ctx, err)
return
}
app.writeJSON(ctx, http.StatusOK, data)
}
}
func (app *Config) deleteProjectHandler() gin.HandlerFunc {
return func(ctx *gin.Context) {
_, cancel := context.WithTimeout(context.Background(), appTimeout)
projectId := ctx.Param("projectId")
defer cancel()
data, err := app.deleteProject(projectId)
if err != nil {
app.errorJSON(ctx, err)
return
}
app.writeJSON(ctx, http.StatusAccepted, fmt.Sprintf("Project with ID: %s deleted successfully!!", data))
}
}
上面的摘要执行以下操作:
- 导入所需的依赖项
- 创建一个
createdProjectHandler
,getProjectHandler
,updateProjectHandler
和deleteProjectHandler
函数,该功能返回杜松子酒处理程序,并将Config
结构作为指针接收。在返回的处理程序中,我们定义了API超时,使用了助手功能,并较早创建的服务执行相应的操作。
更新使用处理程序的API路由
完成此操作,我们现在可以使用处理程序更新routes.go
文件,如下所示:
package api
import "github.com/gin-gonic/gin"
type Config struct {
Router *gin.Engine
}
func (app *Config) Routes() {
app.Router.POST("/project", app.createdProjectHandler())
app.Router.GET("/project/:projectId", app.getProjectHandler())
app.Router.PATCH("/project/:projectId", app.updateProjectHandler())
app.Router.DELETE("/project/:projectId", app.deleteProjectHandler())
}
将它们全部放在一起
通过完全设置API,我们需要创建应用程序输入点。为此,我们需要在cmd
文件夹中创建一个main.go
文件,然后添加下面的摘要:
package main
import (
"go-appwrite/api"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
//initialize config
app := api.Config{Router: router}
//routes
app.Routes()
router.Run(":8080")
}
上面的摘要执行以下操作:
- 导入所需的依赖项
- 使用
Default
配置创建杜松子路由器 - 通过传递
Router
初始化Config
结构 - 添加路线并在端口
:8080
上运行应用程序
完成此操作,我们可以使用以下命令启动开发服务器:
go run cmd/main.go
我们还可以通过在AppWrite上检查集合来确认项目管理数据。
结论
这篇文章讨论了什么是AppWrite,并提供了详细的分步指南,用于在GO中构建项目管理API。
这些资源也可能有帮助: