跳转至

2022

使用golang进行rpc开发之三使用grpc进行开发

前两篇文章介绍了在golang中使用原生的rpc和使用json做为序列化工具进行rpc开发,但是它们都有着各自的缺点,原生的rpc不能跨语言,json在序列化和反序列化时效率又不高,所以本文我们再来学习一下grpc的使用,它完美的解决了它们的缺点

  1. 安装protoc

https://github.com/protocolbuffers/protobuf/releases 将下载的可执行文件放到对应系统的环境变量中,windows 中可以将protoc 目录添加到环境变量,mac 中可以将protoc 文件放到 /usr/local/bin 目录下,输入 protoc --version 来验证一下是否执行成功。

  1. 安装对应语言的插件, golang 中为

    go install github.com/golang/protobuf/protoc-gen-go@latest
    
    安装成功之后会在$GOPATH/bin/目录下生成一个protoc-gen-go 文件

  2. 编写 proto 文件

proto 文件与go 中的结构体一一对应,如果我们在go 中定义一个User的结构体

1
2
3
4
5
type User struct{
    Name string
    Age int
    Frends []string
}

使用golang进行rpc开发之二使用json进行开发

上文介绍了如何在golang 中使用原生的net/rpc 进行开发,但是使用原生的rpc有一个问题,不能跨语言,只能服务端和客户端都是golang时才可以,本文介绍如何使用json作为序列化在不同的语言间进行rpc调用。

首先我们先来修改一个服务端的代码,之前的代码中,服务端收到客户端发来的数据以后,是通过 rpc.ServeConn(conn)来处理请求的

for {
    fmt.Println("等待连接。。。。")
    // 3. 建立连接
    conn, err := lister.Accept()
    if err != nil {
        fmt.Println(err)
    }
    // 4. 绑定服务
    rpc.ServeConn(conn)
}

如果要使用json来处理的话,只需要将原来的rpc.ServeConn(conn)修改为 rpc.ServeCodec(jsonrpc.NewServerCodec(conn))即可。

使用golang进行rpc开发之一使用原生rpc开发

很早之前也了解过一些rpc, 但是心理始终接受不了这种东西,觉得http 用的好好的,为什么要那么麻烦的使用rpc? 且还要定义什么proto 文件 ,后来看了一篇文章 ,既然业内都在使用并且都快成为一种行业标准了,必然有它的优势。 以下是文章原文

既然有HTTP协议,为什么还要有RPC

一、go中原生的rpc开发

go 标准库的 net\rpc 对rpc原生的支持,我们先来看一下使用go标准库是如何开发rpc应用的。 服务端开发主要分为以下四步

  1. 注册rpc服务
  2. 设置端口监听
  3. 等待连接
  4. 服务调用

golang中的锁

在golang中,goroutine 可以理解为其它语言中的线程,在其它语言中存在的数据竞态的问题,在golang中同样存在

本文记录一下数据竞态与各种锁的使用

race condition 竞争状态

这个词也没有听起来很高大上,其实并没有什么新鲜的东西,就是多个协程对同一个变量进行读写,造成了状态不一致,得不到正确的结果,我们来看一下代码

package main

import (
    "fmt"
    "sync"
)

var data int

func incr(wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 10000; i++ {
        data = data + 1
    }
}

func main() {
    wg := sync.WaitGroup{}
    wg.Add(2)
    go incr(&wg)
    go incr(&wg)
    wg.Wait()
    fmt.Println(data)

}

通过http库控制请求超时来一窥context的使用

相信很多人对于golang中的context 都有一定的了解,都知道它是一个上下文管理,有一个根context, 再通过这个根context 创建出有更多功能的context, 如具有cancel 功能的,有timeout功能的。 我们搜索的时候,我们可能看到最多的就是以下的代码

一文详解gin框架中使用单元测试

作为一名合格的开发人员,写单元测试可以很好的梳理代码逻辑,让问题尽早的暴露出来,甚至有些公司或者团队会硬性要求开发人员写单元测试用例,并且还要有多少多少的覆盖度, 本文先以简单的函数单元测试为例,一点点的引入http的接口测试,最后再讨论一下gin 框架的单元测试,包括GET与POST方法 以下是本文的内容结构。

yuque_mind

golang 中结构体匿名嵌套时的初始化问题

当创建了两个结构体,其中一个结构体通过匿名嵌套在另一个结构体中,如下面的定义

1
2
3
4
5
6
7
8
9
type Person struct {
    Name string
    Age  int
}

type Student struct {
    Person
    Grade string
}

Person 为匿名结构体嵌套在了Student 内,那么此时如果想要初始化一个Student对象时该如何初始化呢?

golang中使用匿名结构体

在一些项目中, 我们会使用json 来将字符串转为结构体,但是很多时候,这种结构体只会用一次,基本上只会用于反序列化, 对于这种只用到一次的结构体, 我们可以使用匿名结构体. 在gin 接收参数的时候会非常有用, 如我们将要接收的json 参数为

1
2
3
4
5
6
7
{
  "opt": "left", 
  "phoneinfo": [
    {"device_id": 64, "sn": "192.168.110.65:5555"},
    {"device_id": 68, "sn": "192.168.110.164:5555"}
  ]
}
当我们尝试使用json.Unmarshal() 函数将json 字符串转为go中的数据结构时,我们可以有以下几种方式

Go语言解析JSON

本文将说明如何利用 Go 语言将 JSON 解析为结构体和数组,如果解析 JSON 的嵌入对象,如何将 JSON 的自定义属性名称映射到结构体,如何解析非结构化的 JSON 字符串。

JSON 解析为结构体

JSON 的结构是 key-value,最直观的就是将 JSON 解析为结构体,如下 JSON :

1
2
3
4
{
  "name": yuzhou1u,
  "age": 18
}
Go 语言中,提供了一个专门的包 encoding/json ,所以我们在使用这个 JSON 包之前需要在头文件导入:
1
2
3
4
5
6
package main

import (
  "encoding/json"
  "fmt"
)
然后,我们需要定义一个 Go 语言的结构体以便我们能与 JSON 一一对应,比如在 JSON 中我们定义了姓名 name 和年龄 age ,所以需要定义一个结构体(命名可以随意,但最好通俗易懂)的字段与 JSON 字符串中的键相匹配:

golang中map与切片的函数传参

在golang 的函数参数,如果参数是值类型的话,如果在函数中修改参数值是不会影响原变量的,因为在函数操作中是会进行一次值拷贝的,如果希望函数的修改影响原变量,则需要传指针方式。如以下代码,是不会改变原变量的值的.

package main

import (
    "fmt"
)

func teststr(s string) {
    s = "bbb"
}

func main() {
    ss := "aaaa"
    teststr(ss)
    fmt.Println(ss) // 还是aaaa, 不会是bbb
}
经过teststr函数以后,变量ss并没有被修改。如果想要影响原变量,需要传入指针