Go微服务实战
上QQ阅读APP看书,第一时间看更新

第1章 Go语言程序基础

1.1 Hello,World!

按照其他语言的惯例,本节也先用Go语言实现一个简单的Hello, World!程序,先来看一下最简单的代码,如下:


book/chapter01/helloworld/hello.go
1.  package main
2.
3.  import "fmt"
4.
5.  func main() {
6.      fmt.Println("Hello,World!")
7.  }

说明

本书略过了Go语言环境的安装,请读者自行查阅安装。建议读者在练习的时候每一节设置一个包(package),在此包下创建对应的.go文件后,就可以在该文件所在的目录下直接执行程序了,本例为go run hello.go。

假设上面的代码命名为hello.go,那么可在该目录下通过以下命令行执行该程序:


1. $ go run hello.go

然后可以在终端看到运行结果:Hello,World!

Go语言是编译型语言,虽然本例只是执行了go run这一个指令,后台对应的处理流程却仍然是先编译为二进制机器指令,然后链接相关资源运行,最后输出结果。当然,我们也可以把编译和执行分为两步来完成,即先用go build指令进行编译,然后找到生成的二进制程序,并直接在命令行执行。对应本例,读者可以在hello.go所在目录下的命令行中执行如下命令:


1. $ go build ./hello.go

这样就可以看到在同一个目录下生成了二进制程序hello。然后直接在命令行输入:


1. $ ./hello

这样就可以看到与执行go run命令一样的结果输出了。

说明

还记得本书前言部分的示例代码吗?那里打印了汉字。如果读者是有经验的程序员,一定会猜到Go语言是原生支持Unicode的,所以用户可以方便地处理汉字及其他各种语言文字。

Go语言非常简洁。“Hello,World!”程序虽然简单,但是非常具有代表性,接下来看一下程序结构:

第1行是包的声明。本例中是main包,也是每个项目的入口,main包是独立的可执行程序。包是Go语言项目结构的核心组成,如果其他Go程序要导入已有的程序,要通过导入(import)对应的包来实现。每个Go语言程序的第一行都是包的声明,每个包可以有一个或多个以.go为扩展名的文件。

第3行通过使用import导入了Go语言提供的标准包fmt,Go语言提供了一百多个标准包,后面会根据需要进行介绍。此外,用户自己开发的包也可通过这种方式导入,在import关键字后面的括号中,可以写入用到的多个包。

注意

使用import导入的包必须在本程序中用到。如果导入了却没有使用,则编译无法通过。同样,声明的变量也必须用到,否则也无法编译通过。这是Go语言的优良特性之一。

第5行定义了一个函数,func是定义函数和方法的关键字,会在第3章具体介绍。现在我们只需知道,func关键字后面是函数名,括号内是参数列表。函数体是用大括号括起来的。

第6行使用fmt的Println函数打印一个字符串。可以看到函数名的第一个字母是大写的,首字母大写代表包外可见。还有,语句后面不需要加分号,这一点Python程序员应该比较熟悉。

注意

Go语言其实也可以使用分号,比如把多行代码写在一行的时候,不过不建议那样做,因为不便于阅读。既然Go语言没有分号,又如何解析语句呢?Go语言在这一点上有些类似于Python,又不同于Python。Go语言在编译的时候会把换行符解析为分号,所以大家写Go语言程序的时候要注意换行,即不要把函数的大括号单独作为一行,那样编译是通不过的。此外,还请注意Go语言的代码格式,不过IDE会自动检查并纠正。对于代码编辑器,可以选择VSCode或者Goland,此处首推Goland,因为它的提示功能非常强大。

仅仅这个程序还不足以体现Go语言的简洁和开发的高效,下面再来换一种方式实现这个Hello World!程序。

首先来看以下代码:


book/chapter01/1.1/helloserver/main.go
1. package main
2.
3. import (
4.     "fmt"
5.     "log"
6.     "net/http"
7. )
8.
9. func handler(w http.ResponseWriter,r *http.Request)  {
10.     s := "你好,世界!"
11.     fmt.Fprintf(w,"%s",s)
12.     log.Printf("%s",s)
13. }
14. func main() {
15.     fmt.Println("server start.")
16.     http.HandleFunc("/",handler)
17.     if err := http.ListenAndServe("localhost:1234",nil); err != nil {
18.         log.Fatal("ListenAndServe:",err)
19.     }
20. }

使用Go语言开发Web服务是不需要用户单独安装其他服务器的,直接使用标准的net/http包就可以构建Web服务了,正如上面的代码所示。这段代码实现的功能非常简单,即通过fmt.Fprintf函数向http请求打印字符串。执行本程序后,可以看到在控制台上会输出“server start.”,然后在浏览器中访问地址localhost:1234,这时候可以看到页面显示:


你好,世界!

同时,控制台也会打印这个字符串。

下面介绍上一段代码中比较重要的几行:

第9行至第13行,这是函数handler的定义,其参数是固定的,因为要满足接口的要求,具体情形会在后面介绍。请注意第2个参数,前面带有“*”,表明此处参数传递的是指针。http.Request代表一次请求,是一个结构体。指针和结构体都会在后文介绍。在第10行中,:=表示声明与赋值两个动作一并完成,如果仅仅是声明而不赋值需要使用var关键字,且:=必须是未声明的变量。

第16行会将路径和处理函数绑定,当根路径要进行访问时,交给handler函数处理。

第17行至第19行,启动Web服务,并监听相应端口。

通过这个例子可以更为直观地感受到Go语言的简洁。标准包提供了应有的功能,使用的时候方便快捷。具体的Web编程会在第9章详细介绍,此处的代码仅供读者提前熟悉Go语言的风格。