后端程序员为什么选择go?
后端程序员为什么选择go?
- 语法简单,入门快
- 编译型语言,性能高,语言原生支持并发对后端程序员很有吸引力
- 开发效率高,对于写api的后端程序员来说,golang的开发效率非常接近python,php等脚本语言
- 社区活跃,大牛项目多,高质量的代码都可以任意阅读 (etcd,docker,k8s)
先看一个demo
package main
import (
"io"
"net/http"
)
func helloHandler(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "hello, world!\n")
}
func main() {
http.HandleFunc("/", helloHandler)
http.ListenAndServe(":8888", nil)
}
$ go run main.go
这个demo程序实现一个weh服务,浏览器(或者curl)访问 http://localhost:8888/ 会显hello, world
现在来用ab工具来做下基准测试,100个client请求1w次的结果(环境 deepin golang 1.12.1 no nginx)。
$ ab -n 10000 -c 100 http://localhost:8888/
结果
Concurrency Level: 100
Time taken for tests: 0.425 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 1310000 bytes
HTML transferred: 140000 bytes
Requests per second: 23556.40 [#/sec] (mean)
Time per request: 4.245 [ms] (mean)
Time per request: 0.042 [ms] (mean, across all concurrent requests)
Transfer rate: 3013.56 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 2 0.4 2 4
Processing: 1 2 0.6 2 6
Waiting: 0 2 0.6 2 5
Total: 2 4 0.5 4 8
Percentage of the requests served within a certain time (ms)
50% 4
66% 4
75% 4
80% 4
90% 5
95% 5
98% 6
99% 6
100% 8 (longest request)
现在用php7.2试一下同样的程序效果,比一下(环境 deepin linux nginx1.13.12 100 static php7.2-fpm)
$ ab -n 10000 -c 100 http://localhost/index.php
代码
index.php
<?php
echo "hello world";
结果
Concurrency Level: 100
Time taken for tests: 0.702 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 1490000 bytes
HTML transferred: 110000 bytes
Requests per second: 14237.51 [#/sec] (mean)
Time per request: 7.024 [ms] (mean)
Time per request: 0.070 [ms] (mean, across all concurrent requests)
Transfer rate: 2071.67 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 0.6 1 4
Processing: 1 4 3.6 3 192
Waiting: 1 4 3.5 3 174
Total: 1 5 3.5 4 192
Percentage of the requests served within a certain time (ms)
50% 4
66% 5
75% 6
80% 6
90% 8
95% 9
98% 12
99% 21
100% 192 (longest reques)
对比结果golang在简单的hello world 程序下qps大概是php7.2的2倍。需要注意的是golang的web程序编译完之后就一个可执行文件,不依赖第三方库,这个可执行文件可以在任意linux系统上运行,不需要而外配置环境变量,这个和c和c++编译完的程序运行方式不太一样。c和c++即使是完全静态编译后,还需要看libc版本是不是和编译时的是否兼容,golang的这种特性,在容器化和微服务化的项目中非常占优。php的程序按照目前的主流架构,是需要nginx和php-fpm两个程序配合,同时把代码部署到站点目录。
改进demo程序 实现全局计数器
package main
import (
"fmt"
"io"
"net/http"
"sync/atomic"
)
var counter int32 = 0
func helloHandler(w http.ResponseWriter, req *http.Request) {
atomic.AddInt32(&counter, 1)
io.WriteString(w, "hello, world!")
}
func getCounter(w http.ResponseWriter, req *http.Request) {
atomic.AddInt32(&counter, 1)
io.WriteString(w, fmt.Sprintf("count : %d", atomic.LoadInt32(&counter)))
}
func main() {
http.HandleFunc("/", helloHandler)
http.HandleFunc("/count", getCounter)
http.ListenAndServe(":8888", nil)
}
两个接口 http://localhost:8888/count 和 http://localhost:8888/ 都会对全局counter 原子性加1,注意golang 的http Handle fution 是运行在golang goroutine(协程)里头,goroutine 是并发运行的,所以对全局的counter修改会有data race(数据竞争),需要加锁或者使用原子操作,这边使用golang的原子操作包实现
$ curl http://localhost:8888/count count : 1
$ curl http://localhost:8888/count hello, world //count : 2
$ curl http://localhost:8888/count count : 3
后续的课程章节会学习到golang的http server是如何运行的。
总结
本节课用一个简单的golang web demo实现了hello world程序,同时实现了一个简单的全局计数器。golang官方包支持http server,对于一些简单的api项目用官方包实现起来十分便捷。