您是否曾经觉得构建API就像创建一个秘密代码,只有少数人能理解?作为Web开发人员 - ¾ââ»和TechWriterð,我去过那里。但是不要害怕,我的朋友!在本文中,我将向您展示GO如何帮助您解锁API开发的奥秘并使其任何人都可以使用。
因此,让我们深入了解API的世界,然后发现如何轻松创建强大而有效的API。
解释什么是API以及为什么有用
API是一组用于构建软件应用程序的协议,例程和代码。 API指定软件组件应如何相互作用和通信,从而使开发人员更容易构建复杂的软件系统。 API为软件提供了交换数据和执行功能的标准化方式,使开发人员更容易创建新的应用程序,集成现有系统并自动化流程。
API很有用,因为它们允许开发人员创建可以与其他软件系统,服务和数据源进行交互的应用程序。这意味着开发人员不必每次都想构建新应用程序时从头开始,他们可以利用现有的代码,数据和功能来创建新的和创新的产品。 API还使开发人员能够构建可扩展,模块化和可维护的软件产品,从而更容易随着时间的推移添加新功能和功能。
简要说明GO及其对建筑API的好处
Go是Google开发的一种现代编程语言,它在开发人员的构建API中广受欢迎。 Go是一种编译的语言,这意味着它可以生成可以在各种平台上运行的快速有效的代码。 GO还设计为易于读写,使其成为构建大型和复杂软件系统的绝佳选择。
使用GO构建API的关键好处之一是其对并发的绝佳支持。并发是能够同时运行多个任务的能力,并且GO可以轻松编写可以利用多核处理器和其他硬件资源的代码。这意味着GO API可以处理高水平的流量和请求而不会减慢或崩溃。
将GO用于构建API的另一个好处是其对JSON(JavaScript对象符号)的内置支持,这是一种轻巧的数据格式,在Web应用程序中广泛用于数据交换。 GO对JSON的支持使创建可以以这种格式接受和返回数据的API易于简化构建和集成API与其他软件系统的过程。
总的来说,GO是一种强大而灵活的语言,非常适合构建API。它的速度,并发支持和内置的JSON支持使其成为希望创建可扩展,高性能API的开发人员。
设置GO环境
- 安装GO
第一步是下载并安装在计算机上。您可以从官方Go website下载最新版本的GO。下载后,按照操作系统的安装说明。
- 配置环境变量
安装GO后,您需要配置环境变量。在Windows中,您可以通过右键单击“我的计算机”并选择“属性”来执行此操作。从那里,单击“高级系统设置”,然后单击“环境变量”。将路径添加到GO BIN文件夹中的“路径”变量。
在Linux和MacOS中,您需要在主目录中编辑.bashrc
或.bash_profile
文件,并添加以下行:
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
- 设置工作区
接下来,您需要为您的GO项目设置工作区。工作区是包含您的GO源代码文件和二进制文件的目录。
在主目录中创建一个名为go-workspace
的目录:
$ mkdir ~/go-workspace
在此目录中,创建三个子目录:src
,pkg
和bin
。
$ cd ~/go-workspace
$ mkdir src pkg bin
您准备开始使用GO构建API!
构建API
- 选择一个框架(例如Gorilla Mux,Echo,Gin)
现在我们已经设置了GO环境,我们可以开始构建API。第一步是选择一个框架。有几个流行的框架,用于在GO中构建API,例如Gorilla mux,Echo和Gin。在本文中,我们将使用Gorilla mux
。
- 创建基本服务器
要创建基本服务器,我们需要导入必要的软件包并定义主要功能。主要功能是我们程序的入口点。这是使用大猩猩Mux的基本服务器的示例:
package main
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
)
func main() {
router := mux.NewRouter()
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello, World!")
})
http.ListenAndServe(":8000", router)
}
此代码导入“ FMT”,“ Net/http”和“ github.com/gorilla/mux”软件包,定义了使用Gorilla Mux创建新路由器的主函数,为“/// “路线写着“你好,世界!”向响应作者,并启动了在端口8000上听的HTTP服务器。
- 添加不同端点的路由和处理程序
要为不同端点添加路由和处理程序,我们需要定义其他处理程序功能并将其注册为路由器。
// Define a handler function for the /users endpoint
func getUsersHandler(w http.ResponseWriter, r *http.Request) {
// Get the list of users from the database
users := getUsersFromDB()
// Convert the list of users to JSON format
usersJSON, err := json.Marshal(users)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Set the content type of the response to JSON
w.Header().Set("Content-Type", "application/json")
// Write the JSON response to the client
w.Write(usersJSON)
}
// Register the /users endpoint with the router
r.HandleFunc("/users", getUsersHandler).Methods(http.MethodGet)
在此示例中,我们定义了一个getUsersHandler
函数,该功能从数据库中检索用户列表,将其转换为JSON格式,并将其写入响应。然后,我们通过调用r.HandleFunc("/users", getUsersHandler).Methods(http.MethodGet)
注册该处理程序功能。
我们可以类似地为其他端点定义和注册处理程序功能,例如用于通过ID检索特定用户的/users/{id}
,使用HTTP POST方法来创建新用户的/users
,使用HTTP PUT方法来更新用户,以及使用/users/{id}
和/users/{id}
,以及HTTP删除用于删除用户的方法。
- 实施CRUD操作:
要实现CRUD操作(创建,读取,更新,删除),我们需要为每个操作定义处理程序功能并向路由器注册。
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"github.com/gorilla/mux"
)
type Book struct {
ID string `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Author string `json:"author,omitempty"`
Publisher *Company `json:"publisher,omitempty"`
}
type Company struct {
Name string `json:"name,omitempty"`
Address string `json:"address,omitempty"`
}
var books []Book
func GetBooks(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(books)
}
func GetBook(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
for _, item := range books {
if item.ID == params["id"] {
json.NewEncoder(w).Encode(item)
return
}
}
json.NewEncoder(w).Encode(&Book{})
}
func CreateBook(w http.ResponseWriter, r *http.Request) {
var book Book
_ = json.NewDecoder(r.Body).Decode(&book)
books = append(books, book)
json.NewEncoder(w).Encode(book)
}
func UpdateBook(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
for index, item := range books {
if item.ID == params["id"] {
books = append(books[:index], books[index+1:]...)
var book Book
_ = json.NewDecoder(r.Body).Decode(&book)
book.ID = params["id"]
books = append(books, book)
json.NewEncoder(w).Encode(book)
return
}
}
json.NewEncoder(w).Encode(books)
}
func DeleteBook(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
for index, item := range books {
if item.ID == params["id"] {
books = append(books[:index], books[index+1:]...)
break
}
}
json.NewEncoder(w).Encode(books)
}
func main() {
router := mux.NewRouter()
books = append(books, Book{ID: "1", Title: "Book One", Author: "John Doe", Publisher: &Company{Name: "Publisher One", Address: "Address One"}})
books = append(books, Book{ID: "2", Title: "Book Two", Author: "Jane Smith", Publisher: &Company{Name: "Publisher Two", Address: "Address Two"}})
router.HandleFunc("/books", GetBooks).Methods("GET")
router.HandleFunc("/books/{id}", GetBook).Methods("GET")
router.HandleFunc("/books", CreateBook).Methods("POST")
router.HandleFunc("/books/{id}", UpdateBook).Methods("PUT")
router.HandleFunc("/books/{id}", DeleteBook).Methods("DELETE")
log.Fatal(http.ListenAndServe(":8000", router))
}
此代码使用ID
,Title
,Author
和Publisher
字段定义了Book
结构。然后,它定义了处理程序的功能,以获取所有书籍,通过ID获取特定书籍,创建新书,更新现有书籍并删除书籍。这些处理程序功能使用Gorilla Mux的Vars
函数从URL提取变量,并且它们使用json
软件包来编码和解码JSON数据。最后,设置路由器并使用适当的HTTP方法和URL路径注册处理程序功能,从而使API接收并响应请求。这会创建一个功能齐全的恢复API,可以将其部署到服务器上,并由客户用来对书籍集合进行CRUD操作。
在此示例中,您可以使用GO和Gorilla Mux开始建立自己的API,并自定义以满足您的特定需求。
处理错误和例外
处理错误和异常是构建任何软件的重要方面,API也不例外。构建API时,重要的是要预测和处理运行时可能发生的错误和例外。
某些用于处理错误和GO API例外的技术是:
- 处理程序功能中的错误处理:
处理错误API中错误和异常的一种方法是在处理程序功能中使用错误处理。
func getUser(w http.ResponseWriter, r *http.Request) {
// ...code to get user by ID...
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// ...return user as JSON...
}
如果在获取用户时发生错误,则将作为HTTP 500内部服务器错误返回。
- 自定义错误类型:
在GO中,您可以定义自定义错误类型以表示API中可能发生的特定错误。
type UserNotFoundError struct {
ID int
}
func (e UserNotFoundError) Error() string {
return fmt.Sprintf("user with ID %d not found", e.ID)
}
当找不到具有给定ID的用户时,定义了自定义错误类型UserNotFoundError
表示错误。它可以在处理程序功能中使用:
func getUser(w http.ResponseWriter, r *http.Request) {
// ...code to get user by ID...
if err != nil {
if _, ok := err.(UserNotFoundError); ok {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// ...return user as JSON...
}
如果发生了UserNotFoundError
类型的错误,将其返回为HTTP 404。
- 恐慌和恢复:
处理错误API中错误和异常的另一种方法是使用恐慌和恢复机制。
func getUser(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
log.Println("recovered from panic:", r)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
// ...code that may panic...
}
如果处理程序功能中发生恐慌,将被捕获并记录下来,并将http 500内部服务器错误返回客户端。
通过实施这些技术,您可以确保您的GO API强大,并且可以优雅地处理错误和异常。
与数据库集成
与数据库集成是构建准备生产的API的关键步骤。有许多数据库可供选择,例如MySQL,PostgreSQL,MongoDB等。在本节中,我们将介绍与数据库集成的步骤。
- 选择数据库(例如MySQL,PostgreSQL,MongoDB)
数据库的选择取决于项目的特定需求。例如,如果应用程序需要高度关系数据模型,则基于SQL的数据库(例如MySQL或PostgreSQL)可能是最佳选择。另一方面,如果数据更面向文档或非结构化,则NOSQL数据库(例如MongoDB)可能更合适。选择适合项目需求的数据库,同时考虑诸如性能,可伸缩性和成本等因素。
。- 安装必要的驱动程序
要与特定数据库集成,我们需要安装适当的驱动程序或软件包。例如,要使用MySQL,我们可以安装“ GO-SQL-DRIVER/MYSQL”软件包。同样,我们可以使用“ PQ”软件包连接到PostgreSQL,或者可以连接到MongoDB的“ Mongo-go-driver”软件包。
- 创建数据库连接
安装了必要的软件包后,我们可以创建一个数据库连接。连接字符串通常包含连接到数据库所需的凭据,例如用户名,密码和数据库名称。
创建与MySQL数据库的连接:
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
func main() {
db, err := sql.Open("mysql", "user:password@tcp(host:port)/database")
if err != nil {
// handle error
}
defer db.Close()
// do something with db
}
- 实施数据库操作(例如,查询,插入,更新,删除)
数据库操作(例如查询,插入,更新和删除数据)可以在连接后执行。
从MySQL数据库中检索所有用户的功能:
func getUsers(db *sql.DB) ([]User, error) {
var users []User
rows, err := db.Query("SELECT * FROM users")
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
var user User
err := rows.Scan(&user.ID, &user.Name, &user.Email)
if err != nil {
return nil, err
}
users = append(users, user)
}
return users, nil
}
将GO与数据库集成是构建准备生产的API的关键步骤。
选择适当的数据库,安装必要的驱动程序,创建连接并实现数据库操作。
增加身份验证和授权
将身份验证和授权添加到API中对于确保安全访问和控制敏感数据很重要。这是解决方法:
- 选择一种身份验证和授权方法(例如JWT,OAUTHZ)
首先,选择适合API需求的身份验证和授权方法。常见方法包括JWT(JSON Web令牌),OAUTH2和基本身份验证。
- 实施身份验证和授权中间件
接下来,您需要实现中间件功能来处理身份验证和授权。这些功能应检查有效的身份验证凭据,并根据用户的角色和权限授权访问端点。
基本的JWT身份验证中间件功能:
func RequireTokenAuthentication(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
http.Error(w, "Missing authorization header", http.StatusUnauthorized)
return
}
token, err := jwt.Parse(authHeader, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte("secret"), nil
})
if err != nil {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
if !token.Valid {
http.Error(w, "Invalid token", http.StatusUnauthorized)
return
}
context.Set(r, "decoded", token.Claims)
next.ServeHTTP(w, r)
})
}
- 将身份验证和授权添加到端点
实现了中间件后,我们可以将其添加到所需的端点。例如,要限制对具有特定角色的认证用户的访问,我们可以使用RequireTokenAuthentication
middleware并添加角色检查:
router.HandleFunc("/protected", RequireTokenAuthentication(ProtectedHandler)).Methods("GET")
测试API
要确保API正常运行,我们需要编写测试。务必进行彻底测试,以确保其按预期工作,并在与用户联系之前捕获任何错误或问题。
可以将测试分为单个处理程序和端点的单位测试,以及整个API的集成测试。 GoConvey和Ginkgo等测试框架可以帮助编写和运行测试。
- 编写终点和处理程序的单元测试。
单元测试的重点是测试代码的单个功能或组件。对于我们的API,我们需要为每个端点和处理程序功能编写单元测试,以确保它们正常工作。
这是处理程序的测试功能:
func TestProtectedHandler(t *testing.T) {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"username": "testuser",
"role": "admin",
"exp": time.Now().Add(time.Hour * 24).Unix(),
})
tokenString, err := token.SignedString([]byte("secret"))
if err != nil {
t.Fatalf("Error signing token: %v", err)
}
req, err := http.NewRequest("GET", "/protected", nil)
if err != nil {
t.Fatalf("Error creating request: %v", err)
}
req.Header.Set("Authorization", "Bearer "+tokenString)
rr := httptest.NewRecorder()
handler := http.HandlerFunc(ProtectedHandler)
handler.ServeHTTP(rr, req)
if status := rr.Code; status != http.StatusOK {
t.Errorf("Handler returned wrong status code: got %v want %v", status, http.StatusOK)
}
expected := `{"message":"Hello, authenticated user!"}`
if rr.Body.String() != expected {
t.Errorf("Handler returned unexpected body: got %v want %v", rr.Body.String(), expected)
}
}
- 编写API的集成测试:
集成测试测试了API,以确保所有组件都正确地工作。
使用银杏测试框架的集成测试:
var _ = Describe("API", func() {
var (
apiURL string
api *API
)
BeforeEach(func() {
apiURL = "http://localhost:8080"
api = NewAPI()
go api.Start()
time.Sleep(1 * time.Second)
})
AfterEach(func() {
api.Stop()
})
Describe("GET /users", func() {
It("returns a list of users", func() {
resp, err := http.Get(fmt.Sprintf("%s/users", apiURL))
Expect(err).NotTo(HaveOccurred())
defer resp.Body.Close()
Expect(resp.StatusCode).To(Equal(http.StatusOK))
bodyBytes, err := ioutil.ReadAll(resp.Body)
Expect(err).NotTo(HaveOccurred())
bodyString := string(bodyBytes)
Expect(bodyString).To(ContainSubstring("John Doe"))
Expect(bodyString).To(ContainSubstring("johndoe@example.com"))
})
})
})
测试是构建强大的API的重要组成部分,使用GoConvey或Ginkgo等测试框架可以使过程更容易,更有效。
部署API
太好了!开发,测试并准备好生产的API后,我们需要部署它,以便我们的客户可以访问它。根据您的项目要求和基础架构功能,有各种各样的部署方法可供选择。 (例如,Docker,Heroku,AWS)
我们将通过在Heroku上部署API的步骤,这是一个流行的服务(PAAS)提供商。
-
创建一个Heroku帐户:
首先,如果您还没有一个帐户,请创建一个Heroku帐户。访问Heroku website并注册免费帐户。 -
安装Heroku CLI:
接下来,通过按照Heroku网站上的说明下载并安装Heroku CLI。这个CLI将使我们能够从终端与Heroku互动。 -
创建一个新的Heroku应用程序:
安装了Heroku CLI后,通过在终端中运行以下命令来创建一个新的Heroku应用:
heroku create <app-name>
用您要给应用的名称替换<app-name>
。这将在Heroku上创建一个新应用,并为您提供访问它的URL。
- 设置环境变量: 如果您的API使用任何环境变量,例如数据库连接字符串或身份验证键,则需要在Heroku上进行设置。 您可以通过在终端中运行以下命令来执行此操作:
heroku config:set <KEY>=<VALUE>
用环境变量的名称替换<KEY>
,而<VALUE>
则具有其价值。
-
将您的代码提交给git:
在我们可以在Heroku上部署应用程序之前,我们需要将代码提交给GIT。确保您的代码位于git存储库中并提交您所做的任何更改。 -
部署您的应用程序:
当您的代码致力于Git时,您可以通过在终端中运行以下命令将应用程序部署到Heroku:
git push heroku master
这将使您的代码将您的代码推向Heroku并触发构建过程。构建完成后,您的应用程序将在Heroku上启动并运行。
- 缩放您的应用程序: 如果您拥有高流量应用程序,则可以通过在终端中运行以下命令来扩展它:
heroku ps:scale web=<number-of-instances>
用要运行的实例替换<number-of-instances>
。
恭喜!您已成功地将API部署在Heroku上。您现在可以使用Heroku提供的URL访问它。
结论
在本教程中,我们涵盖了GO构建API的基础知识。我们首先了解什么是API以及它们为何有用。然后,我们继续探索使用GO构建API并建立我们的开发环境的好处。
我们了解了选择一个框架并创建基本服务器,为不同端点添加路由和处理程序,实现CRUD操作,处理错误和异常,与数据库集成以及添加身份验证和授权。最后,我们介绍了测试API并使用Docker部署。
尽管我们在本教程中介绍了很多东西,但还有更多关于使用GO构建API的知识。要继续您的学习旅程,请查看下面列出的其他资源:
- Go Documentation
- Go Web Examples
- Create A Simple RESTful API With Golang
- Advanced Go Concurrency Patterns
感谢您的阅读,希望您对此教程有所帮助。如果您有任何疑问或评论,请随时在LinkedIn或Twitter上与我建立联系。如果您真的很喜欢这个教程,则可以buy me a coffee。
Freepik的图像