go:简简单单的并发网络连接

go 是天生支持并发的,我们只要 使用 go func() 就可以快速实现并发。在网络服务的处理中,实现并发可以大大提高服务的吞吐量,我们来研究一下。 简单的TCP服务器 我们先来实现一个简单的tcp服务,监听8989端口,从连接中读取一段数据,这段数据表示的是当前请求的id,然后返回一段话。 服务器 server/main.go package main import ( "fmt" "log" "net" ) func main() { // 启动tcp连接,监听8989端口 l, err := net.Listen("tcp", ":8989") if err != nil { log.Fatalf("Server listening error: %s\n", err) } for { conn, err := l.Accept() if err != nil { log.Printf("Accept error: %s\n", err) continue } // 接收连接,调用handleConn处理当前连接 handleConn(conn) } } func handleConn(conn net....

April 6, 2022 · 6 min · LingZihuan

Go:简单的跨平台rpc服务

RPC RPC - Remote Procedure Call 称为远程过程调用,是分布式系统中,不同节点调用的方式(进程间通信),属于 C/S 模式。由客户端发起,调用服务端的方法进行通信,服务端将结果返回给客户端。 RPC的两个核心: 通信协议 序列化 序列化和反序列化是一种把传输内容编码和解码的方式,常见的编解码方式有 JSON、Protobuf 等。 大多数 RPC 架构中,都有 Client、Client Stub、Server、Server Stub这四个组件,Client 和 Server 通过 Socket 进行通信。 flowchart LR subgraph 服务端进程 s(Server) ss(Server Stub) s --调用--> ss ss --返回--> s end subgraph 客户端进程 c(Client) cs(Client Stub) c --调用--> cs cs --返回--> c end 客户端进程 ==网络消息==> 服务端进程 服务端进程 ==> 客户端进程 调用流程: client 调用 client stub,同时把参数传给 client stub client stub将参数打包编码,然后通过系统调用发送到服务端进程 客户端本地系统发送信息到服务器 服务器系统将信息发送到 server stub server stub 将信息解码 server stub 调用真正的服务端程序 server server 处理后,通过同样的方式,将结果返回到 client go 实现简单的RPC服务 go内置了 net/rpc 包帮助我们实现rpc服务。...

March 30, 2022 · 4 min · LingZihuan

Go:简单的http服务以及Restful Api

简易 http 服务 使用 go 自带的 http 模块实现一个简单的 http 服务器,对请求者说一句 Hello, go http! func main(){ http.HandleFunc("/hello", sayHello) http.ListenAndServe(":8080", nil) } func sayHello(resp http.ResponseWriter, req *http.Request) { log.Println("In say hello") resp.WriteHeader(http.StatusOK) resp.Write([]byte("Hello, go http!")) } 运行上述代码,在终端使用 curl 访问该地址,返回正常: >curl http://localhost:8080/hello Hello, go http! 且程序使用 log 打印了一句: 2022/03/27 15:32:48 In say hello 但是,我们的http方法有很多, GET/POST/PUT/PATCH/DELETE 等,我们使用任意一个方法,访问上述地址,都能得到 Hello, go http! 这句返回,如 POST: >curl -X POST http://localhost:8080/hello Hello, go http!...

March 27, 2022 · 6 min · LingZihuan

17.go: 代码检查和性能优化

对我们的代码进行检查,有助于提高代码质量,确保代码更加符合规范。 使用 golangci-lint 进行代码检查 go语言代码分析的工具有很多,如 golint、gofmt、misspell等,我们一般使用 集成工具 golangci-lint,而不是单独使用他们。 安装 go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.32.2 查看版本 golangci-lint version 输出: golangci-lint has version v1.32.2 ... 运行检查: golangci-lint run quality/ 这里的 quality是一个包,里面有一个 main.go 文件,内容如下: quality/main.go package main import "os" func main(){ os.Mkdir("/tmp", 0666) } 运行检查后,输出如下: quality\main.go:6:10: Error return value of `os.Mkdir` is not checked (errcheck) os.Mkdir("/tmp", 0666) 因为 os.Mkdir 返回一个 error,但是我们没有处理这个 error,因此提示了这个错误。 golangci-lint 配置 golangci-lint是一个集成工具,里面有很多linters,我们可以用 golangci-lint linters 查看有哪些linters,以及他们的作用、启用情况,默认启用的linters如下: deadcode - 死代码检查 errcheck - 返回错误是否使用检查 gosimple - 检查代码是否可以简化 govet - 代码可疑检查,比如格式化字符串和类型不一致 ineffassign - 检查是否有未使用的代码 staticcheck - 静态分析检查 structcheck - 查找未使用的结构体字段 typecheck - 类型检查 unused - 未使用代码检查 varcheck - 未使用的全局变量和常量检查 我们可以通过一个 ....

March 26, 2022 · 2 min · LingZihuan

16.go: 单元测试和基准测试

单元测试 单元测试就是对单元进行测试(听起来是一句废话),单元可以是一个函数、一个模块等,我们最小的单元是一个函数。 以斐波那契数列为例,实现一个测试用例 test/main.go package main // 斐波那契数列 func Fibonacci(n int) int { if n <= 0 { return 0 } else if n == 1 { return 1 } return Fibonacci(n-1) + Fibonacci(n-2) } 我们在 main.go 里面写了一个 Fibonacci函数,用于计算对应的斐波那契值。 我们接下来写一个测试用例,测试的文件名应该是以 _test.go 结尾的,前面的名称最好是需要测试的文件名称,比如要测试 main.go,则测试文件命名为 main_test.go,而在 测试文件里面,需要一个以 Test开头的函数,后面接需要测试的函数名称,如 TestFibonacci,这个函数接受一个 *Testing.T指针,且不返回任何值 test/main_test.go func TestFibonacci(t *testing.T) { result := map[int]int{ 1: 1, 2: 1, 3: 2, 4: 3, 5: 5, 6: 8, 7: 13, 8: 21, } for n, expect := range result { got := Fibonacci(n) if expect !...

March 21, 2022 · 3 min · LingZihuan