3.使用Go语言开发Web服务
微信小程序提供了一系列服务端API用以配合小程序前端来完成相应的功能,以及帮助开发者进行各类数据分析、业务管理和信息查询等操作。例如小程序用户信息的获取就是通过服务端API来完成的。小程序前端要获取小程序用户信息,首先通过前端API获取临时登录凭证,然后把临时登录凭证回传到开发者服务器,开发者服务器调用 auth.code2Session 接口来换取用户唯一标识(OpenID) 和会话密钥(session_key)。因此要实现一个完整的小程序应用,除了掌握前端开发知识,还需要了解服务端开发的内容。一个完整的小程序应用,至少包含一个前端项目以及一个服务端项目。
进行服务端开发首先要进行服务端基础环境的搭建,服务端基础环境的搭建包括以下环节:
1)购买云服务器
可以在国内的各大云平台购置云服务器,可以根据小程序预期的访问量来确定服务器的性能指标以及数量。云服务器要申请外网IP,这个外网IP将用于后面的域名解析服务中。
2)购买域名
基于安全的考虑,小程序访问服务端前需要进行服务器域名的配置。小程序不能直接通过IP来访问服务器,因此上还需要为您的小程序应用购置一个域名。
3)域名备案
域名备案是国家信息产业部的要求,在域名使用前还必须完成备案。
4)域名解析
域名备案成功后就可以进行域名解析的配置,一般是在您购买服务器的云平台进行域名解析配置。您需要将这个域名或者子域名绑定在需要对外提供服务的那台服务器上。
5)购买SSL证书
小程序的大多数接口需要服务端提供HTTPS的访问接口,这就需要为您的域名购买SSL证书。购买成功后将证书下载下来,用于后续配置Web服务器。
完成上述的步骤后,您方可以开始搭建服务端开发环境,进行服务端代码的编写。微信小程序的服务端接口多为HTTP/HTTPS接口,请求或返回的数据基本上是JSON格式,因此任何能够提供HTTP/HTTPS接口服务的开发框架都可以用于小程序服务端的开发。例如您可以使用PHP开发框架或Java开发框架来开发小程序的服务端应用。本文重点介绍如何使用Go语言开发框架来进行小程序的服务端的开发。本章将使用Go语言来实现一个简单的Web服务,不过在进行Web服务编码之前,先介绍一下Go语言的特点,以及一些用于小程序开发的一些相关知识。
3.1 Go语言的特点
Go(又称Golang)是Google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。Go发布之后,很多重要的软件项目都采用了Go进行开发,特别是云计算相关的软件,例如大家都熟悉的Docker就是采用Go开发的。另外越来越多公司都已经采用Go作为服务端开发语言。例如今日头条、UBER这样的公司,他们使用Go语言对自己的业务进行了彻底的重构。Go语言之所如此受到欢迎,是因为它在服务端的开发中,总能抓住服务端开发的一些痛点,并以开发效率的提升作为主要目标。我们来看看Go语言的一些特性:
- 自动垃圾回收
内存和资源管理一直是一个让人非常头痛的难题。在如语言C或C++语言中,使用内存前要先分配这段内存,使用完毕后再将其释放掉,一个小疏忽就可能引发内存泄漏,导致程序崩溃。Go语言继承了JAVA语言自动垃圾回的特性,把内存管理交给Go语言基础环境去做,再也不需要开发人员来管理内存了,从而显著提升开发人员的开发效率。 - 函数多返回值
在C,C++中,包括其他的一些高级语言是不支持多个函数返回值的。但是这项功能又确实是需要的。在C语言中一般通过将返回值定义成一个结构体,或者通过函数的参数引用的形式进行返回。而在Go语言中,允许函数返回多个值,在某些场景下,可以有效的简化编程。 - “非侵入式”接口
Go语言最让人赞叹的特性,就是interface的设计。Go语言实现一个接口不需要显示的进行声明,任何数据结构,只要实现了interface所定义的函数,就自动implement了这个interface。Go语言的这一特性为程序接口的实现和调用提供了非常大的灵活性,可以使您的代码结构更加简洁和清晰。 - 并发与协程
很多语言都支持多线程、多进程编程,但遗憾的是,线程和进行的实现和控制并不是那么令人轻松和愉悦。Go语言提供了协程(goroutine)并发来解决这个问题。协程又称微线程,比线程更轻量、开销更小,性能更高。协程操作起来非常简单,在Go语言中使用关键字”go”来启动一个协程,并且在同一台机器上可以启动成千上万个协程。 - Defer延迟处理机制
在Go语言中,提供了关键字defer,可以通过该关键字指定需要延迟执行的逻辑体。defer中的逻辑体会在函数体return前或出现panic时执行。这种机制非常适合善后逻辑的处理,比如用于及时释放数据库连接。对defer的引入,在很大程度上可以简化编程,并且在语言描述上显得更为自然,极大的增强了代码的可读性。 - 高性能HTTP Server
作为出现在云计算时代的服务端语言,Go在语言级别自带HTTP/TCP/UDP高性能基础框架,为Web应用的开发提供有效的支持。要在Go语言中实现一个高性能的HTTP Server,只需要几行代码即可完成,非常简单。
3.2 Go开发环境搭建
3.2.1 Go安装
Go安装包下的载与安装
Go语言安装包下载地址为:官方网站:https://www.golang.org,国内网站:https://golang.google.cn。您可以根据您电脑的操作系统选择合适的版本来下载。
配置Windwos环境变量
执行完Go安装程序后需要配置以下几个环境变量:
1)GOROOT环境变量
GOROOT是Go的安装目录,例如:c:\go
go1.11版本之前需要手工配置GOROOT,go1.11版本之后的安装程序会自动配置GOROOT。
2)Path环境变量
Path环境变量用于设置可执行文件的搜索路径,需要把Go安装路径下的bin目录添加到Path环境变量中, 例如:%GOROOT%\bin
go1.11版本之前需要手工配置Path,go1.11版本之后的安装程序会自动将%GOROOT%\bin添加到Path环境变量。
3)GOPATH环境变量
GOPATH是Go的工作空间,GOPATH下通常有src,bin,pkg三个文件夹,src用来放源码,bin目录用来放编译好的可执行文件,pkg用来存放第三方依赖包。
go1.11版本之后,推荐使用go mod模式来管理程序包依赖,不再强制要求把代码写在GOPATH下面。Go Module功能开启后,下载的包将存放在$GOPATH/pkg/mod路径中。
配置GOPROXY
GOPROXY用于设置第三方Module的下载地址。从Go 1.13开始,Go Module作为Go中的标准包管理器,在安装时自动启用,并附带一个默认的GOPROXY。首先使用 go env来查看Go相关的环境变量:
set GO111MODULE=
set GOARCH=386
set GOBIN=
set GOCACHE=C:\Users\fs\AppData\Local\go-build
set GOENV=C:\Users\fs\AppData\Roaming\go\env
set GOEXE=.exe
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=D:\GoApp
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=D:\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=D:\Go\pkg\tool\windows_amd64
set GCCGO=gccgo
Go默认的GOPROXY是https://proxy.golang.org,由于国内访问不到https://proxy.golang.org,所以我们需要换一个PROXY:
go env -w GOPROXY=https://goproxy.cn,direct
3.2.2 Go Module
在Go版本1.11之前所有的Go项目,都需要放在GoPath下的src目录下才能够编译运行。这种代码管理方式实际操作中会有如下问题:
- 如果我们把所有项目都放在同一个GoPath的src包下,那么项目的结构就会变得非常混乱,难以管理。
- 如果我们建立不同的GoPath来管理我们的项目,那么不同GoPath下的src中下载大量重复的第三方依赖包,这同样会占用大量的磁盘空间。
为了解决项目依赖管理问题,go1.11版本引入了GoModule的概念。GoModule就是一个用来取代GoPath的Go的工作空间,GoPath用来存放从网上拉取的第三方依赖包,GoModule用来存放我们自己的Go项目文件。go1.11版本之后,推荐使用go mod模式来管理依赖环境了,不再强制我们把代码写在GOPATH下面的src目录了,你可以在你电脑的任意位置编写Go代码。
使用GoModule首先需要设置go mod模式,Go通过环境变量GO111MODULE来设置go mod模式。GO111MODULE 有三个可选值:off、on、auto,默认值是auto: - GO111MODULE=off禁用模块支持,编译时会从GOPATH文件夹中查找包。
- GO111MODULE=on启用模块支持,编译时会忽略GOPATH文件夹,只根据 go.mod下载依赖。
- GO111MODULE=auto,当项目在$GOPATH/src外且项目根目录有go.mod文件时,自动开启模块支持。
若要开启GoModule支持,请输入以下命令:
go env -w GO111MODULE=on
新建项目
在任意路径下(除GOPATH以外)创建项目目录hello, 新建 hello.go文件,并输入以下代码:
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, World!")
}
进入代码根目录执行 go mod init 包路径:
$ go mod init hello
执行完成命令之后,代码根目录会生成 go.mod文件。文件内容为:
module hello
go 1.13
引用第三方模块
修改 hello.go 文件,引入第三方模块
package main
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
_ "gopkg.in/yaml.v2"
)
func main() {
fmt.Println("Hello, World!")
}
如果代码中有外部依赖的包,在执行会触发编译 go 命令的时候(如 go run, go build, go install, go test 等)会自动在 go.mod 中自动添加依赖:
$ go build
go: downloading github.com/go-sql-driver/mysql v1.6.0
go: downloading gopkg.in/yaml.v2 v2.4.0
go: extracting github.com/go-sql-driver/mysql v1.6.0
go: extracting gopkg.in/yaml.v2 v2.4.0
go: finding gopkg.in/yaml.v2 v2.4.0
go: finding github.com/go-sql-driver/mysql v1.6.0
执行go build后的 go.mod文件内容为:
module hello
go 1.13
require (
github.com/go-sql-driver/mysql v1.6.0
gopkg.in/yaml.v2 v2.4.0
)
下载下来的依赖,会保存在 $GOPATH/pkg/mod 目录下:
图3-1 $GOPATH/pkg/mod 目录
3.2.3 Go代码编辑器
适用于Go语言的代码编辑器有很多,任何一款文本编辑器都可以做Go语言开发的编辑器。这里推荐使用VS Code和JetBrains GoLand。 VS Code是微软开源的编辑器,而Goland是jetbrains出品的一款IDE。JetBrains GoLand是目前JetBrains针对Go语言开发的最新Go语言编程工具,工具十分的好用,集成了非常不错的功能,而且针对Go语言做出了不少的优化。
3.3简单的Web服务器
具备了Go语言的基础知识后就可以开始开发一个简单的Web服务器,并尝试实现一个增强版的Hello World小程序。在这个小程序应用中,小程序客户端将向Web服务器发送请求,并将Web服务器返回的结果更新到小程序的页面中。
Go Web服务器
Go语言里面提供了一个完善的net/http包,通过net/http包我们可以很方便的搭建一个Web服务器。
示例代码:simple_server.go
package main
import (
"io"
"log"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Hello GoLang")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/hello", hello)
err := http.ListenAndServe(":8001", mux)
if err != nil{
log.Fatal("Error:", err)
}
}
在main函数中,我们从net/http包中调用了一个http.HandleFucn函数来注册一个HTTP请求的处理器函数(简称处理器)。在本例中的hello函数便是一个处理器函数。http.HandleFucn函数接受两个参数。第一个是一个路径字符串,对应HTTP请求中的PATH参数,在本例中是"/hello"。第二个参数是一个func (ResponseWriter, Request)的签名的参数。正如你所见,hello函数就是具有这样的签名的函数。下一行代码中的http.ListenAndServe(":8001", nil),表示监听localhost的8001端口。
在hello函数中也有两个参数,一个是http.ResponseWriter类型的参数。http.ResponseWriter是一个接口类型,表示一个输出流。第二个参数是http.Request类型,对应一个HTTP请求结构。我们目前不必使用所有的参数,我们只需要使用http.ResponseWriter将"Hello world"字符串写入到输出流即可。
在小程序调用之前,可以先在浏览器中测试一下,进入Go代码所在的目录,使用go build 编译,然后执行编译后的可执行文件。若没有异常,则可以打开浏览器,在浏览器地址输入框中输入:http://127.0.0.1:8001/hello, 然后您就可以在浏览器中看到程序的输出结果。使用Go开发一个Web服务器就这么简单,短短几行代码就实现了一个简单的Web服务器。
3.4增强版Hello World
本章重新实现第一章的Hello World小程序,在这个小程序中我们将使用wx.request接口来访问Go语言实现的Web服务器,并将Web服务器返回的结果显示在小程序的页面中。wx.request接口的使用会在后续章节中进行详细说明。
示例代码:index.wxml:
<view>
<view style="text-align:center;padding:200rpx">
<text>{{motto}}</text>
</view>
</view>
示例代码:index.js:
function getWebData(page) {
var url = 'http://127.0.0.1:8001/hello';
wx.request({
url: url,
success: function (res) {
if (res.statusCode === 200) {
page.setData({ motto: res.data });
}
}
});
}
Page({
data: {
motto: ''
},
onLoad() {
getWebData(this);
}
})
在index.js中的页面的onLoad函数中访问我们刚刚建立的Go Web服务器,获取Web服务器返回的结果,并用setData更新绑定数据。
点击小程序开发工具的编译按钮,在左侧的模拟器中可以看到运行结果。若您的Web服务器的URL地址不是域名,而是IP格式的地址,您将不会看到期望的运行结果。在小程序开发工具调试区,您会看到一个错误提示:
request 合法域名校验出错
VM8 asdebug.js:1 如若已在管理后台更新域名配置,请刷新项目配置后重新编译项目,操作路径:“详情-域名信息”
VM8 asdebug.js:1 http://127.0.0.1:8001 不在以下 request 合法域名列表中,请参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html
这是因为使用了IP地址格式的URL或者是服务端的接口没有采用https协议所致。
为了降低开发们门槛,方便开发者进行小程序的开发调试,开发者工具允许wx.request请求任意域名,只需要按照图3-2中的提示配置开发者工具即可:
图 3-2 设置开发者工具
修改上图中的配置项,重新编译小程序,您应该就可以看到正确的输出结果了。