专栏名称: 狗厂
目录
相关文章推荐
51好读  ›  专栏  ›  狗厂

[译]构建第一个Go微服务

狗厂  · 掘金  ·  · 2018-05-18 08:56

正文

第二部分: Go微服务 - 构建我们的第一个服务

第二部分包含:

  • 设置我们的Go工作空间。
  • 构建我们第一个微服务。
  • 通过HTTP使用Gorilla Web Toolkit来提供一些JSON服务。

介绍

虽然通过HTTP提供JSON服务不是内部服务和外部服务的唯一选择,但本文聚焦的是HTTP和JSON. 使用RPC机制和二进制消息格式(例如Protocol Buffer)也用于内部通信或外部通信也是非常有趣的,特别是当外部消费者属于另外一个系统的时候。Go语言有内置的RPC支持,并且gRPC也是完全值得看看的。 然而,我们现在只聚焦基于由http包和Gorilla Web Toolkit提供的HTTP。

另外一个需要考虑的方面是很多有用的框架(安全、跟踪等等), 依赖于HTTP头来传输参与者正在进行的请求状态。我们在本文中将看到的例子是我们如何在头中传递相关ID和OAuth票据。虽然其他协议当然也支持类似的机制, 很多框架都是以HTTP构建的,我更愿意尽可能的保持我们的集成更加直接。

设置Go工作空间

如果你是一个经验丰富的Go开发者,你可以随意跳过本节内容。 以我拙见,Go语言工作空间结构需要一些时间来适应。一般来说我习惯使用项目根作为工作空间的根,Go语言约定了如何恰当的构造工作空间,因此go编译器可以查找源代码和依赖,有点不正统, 将源代码放在子目录下源码控制路径后以src命名的目录中.我强烈推荐读下官方指南和本文,然后再开始。 我希望我就是这样的。

安装SDK

在开始写我们第一行代码之前(或check out完整代码之前), 我们需要安装Go语言SDK。建议按照官方指导来操作,直接操作就足够了。

设置开发环境

在这些博客系列中,我们将使用我们安装的内置的Go SDK工具来构建和运行我们的代码,以及按照惯用方式来设置Go的工作空间。

1. 创建工作空间的根目录

所有命令都基于OS X或Linux开发环境。 如果你运行的是Windows, 请采用必要的指令。

mkdir ~/goworkspace
cd goworkspace
export GOPATH=`pwd`

这里我们创建了一个根目录,然后将GOPATH环境变量赋于那个目录。这就是我们的工作空间的根目录,我们所写的所有Go语言代码和第三方类库都在它下面。我推荐添加这个GOPATH到.bash_profile文件或类似的配置文件中,这样不需要每次都为每个控制台窗口重置它。

2. 为我们第一个项目创建文件夹和文件

鉴于我们已经在工作空间的根目录(例如,和在GOPATH环境变量中指定相同的目录), 执行下面的语句:

mkdir -p src/github.com/callistaenterprise

如果你希望遵循自己的编码,可以执行下面的命令:

cd src/github.com/callistaenterprise
mkdir -p goblog/accountservice
cd goblog/accountservice
touch main.go
mkdir service

或者你可以clone这个git仓库,包含相同代码,并切换到P2分支。 从上面你创建的src/github.com/callistaenterprise/goblog.git目录, 执行下面的命令。

git clone https://github.com/callistaenterprise/goblog.git
cd goblog
git checkout P2

记住: $GOPATH/src/github.com/callistaenterprise/goblog是我们项目的根目录,并且实际是存储在github上面的。

那么我们结构已经足够可以很方便开始了。 用你喜欢的IDE打开main.go文件。

创建服务 - main.go

Go语言中的main函数就是你具体做事的地方 - Go语言应用程序的入口点。 下面我们看看它的具体代码:

package main

import (
    "fmt"
)

var appName = "accountservice"

func main() {
    fmt.Printf("Starting %v\n", appName)
}

然后运行该程序:

> go run path/to/main.go
Starting accountservice

就是这样的,程序只打印了一个字符串,然后就退出了。是时候添加第一个HTTP端点了。

构建HTTP web服务器

注意: 这些HTTP示例的基础是从一个优秀的博客文章派生出来的, 见参考链接。

为了保持代码整洁,我们把所有HTTP服务相关的文件放到service目录下面。

启动HTTP服务器

在service目录中创建webservice.go文件。

package service

import (
    "log"
    "net/http"
)

func StartWebServer(port string) {
    log.Println("Starting HTTP service at " + port)
    err := http.ListenAndServe(":"+port, nil) // Goroutine will block here

    if err != nil {
        log.Println("An error occured starting HTTP listener at port " + port)
        log.Println("Error: " + err.Error())
    }
}

上面我们使用内置net/http包执行ListenAndServe, 在指定的端口号启动一个HTTP服务器。

然后我们更新下main.go代码:

package main

import (
    "fmt"
    "github.com/callistaenterprise/goblog/accountservice/service" // 新增代码
)

var appName = "accountservice"

func main() {
    fmt.Printf("Starting %v\n", appName)
    service.StartWebServer("6767") // 新增代码
}

然后再次运行这个程序,得到下面的输出:

> go run *.go
Starting accountservice
2017/01/30 19:36:00 Starting HTTP service at 6767

那么现在我们就有一个HTTP服务器,它监听localhost的6767端口。然后curl它:

> curl http://localhost:6767
404 page not found

得到404完全是意料之中的,因为我们还没有添加任何路由呢。

Ctrl+C停止这个web服务器。

添加第一个路由

是时候让我们的服务器提供一些真正的服务了。我们首先用Go语言结构声明我们的第一个路由,我们将使用它来填充Gorilla路由器。 在service目录中,创建一个routes.go文件。

package service

import (
    "net/http"
)

// Define a single route, e.g. a human readable name, HTTP method and the pattern the function that will execute when the route is called.

type Route struct {
    Name        string
    Method      string
    Pattern     string
    HandlerFunc http.HandlerFunc
}

// Defines the type Routes which is just an array (slice) of Route structs.
type Routes []Route

var routes = Routes{
    Route{
        "GetAccount", // Name
        "GET",        // HTTP method
        "/accounts/{accountId}", // Route pattern
        func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Content-Type", "application/json; charset=UTF-8")
            w.Write([]byte("{\"result\":\"OK\"}"))
        },
    },
}

上面代码片段,我们声明了一个路径/accounts/{accountId}, 我们后面会用curl来访问它。Gorilla也支持使用正则模式匹配、schemes, methods, queries, headers值等等的复杂路由。因此不限于路径和路径参数。







请到「今天看啥」查看全文