Go 1.8使用Protocol Buffer
最近在写一个在线客服模块,秉着简单,可控,可维护,可扩展,满足需求的原则,找了一个开源项目: 。
当然对于原始项目,肯定还是需要一些改动的,比如:鉴权,用户体系,文件类型消息的处理(存在阿里云OSS上)等等。
为了满足需求,修改了原始的基于protocol buffer的message,修改后在重新生成对应的go文件时候,遇到了一些问题,可以参考以下解决方法。
github上的protobuf( )已经说明,需要使用: google.golang.org/protobuf 。
安装官方文档 安装对应的插件模块,mac需要在.zshrc文件添加以下内容:
以下是message proto文件:
执行以下命令生产对应的go文件:
client-go 源码分析
client-go是一个调用kubernetes集群资源对象API的客户端,即通过client-go实现对kubernetes集群中资源对象(包括deployment、service、ingress、replicaSet、pod、namespace、node等)的增删改查等操作。大部分对kubernetes进行前置API封装的二次开发都通过client-go这个第三方包来实现。
client-go官方文档:
client-go库版本
获取kubernetes配置文件kubeconfig的绝对路径。一般路径为$HOME/.kube/config。该文件主要用来配置本地连接的kubernetes集群。config配置文件支持集群内和集群外访问方式。(只要在网络策略访问范围内)
config文件形式如下所示:
通过参数(master的url或者kubeconfig路径)用BuildConfigFromFlags方法来获取rest.Config对象,一般是通过参数kubeconfig的路径。
通过config对象为入参,调用NewForConfig函数获取clients对象,clients是多个client的集合。里面包含着各个版本的client。源码地址:k8s.io/client-go/kubernetes/clientset.go
NewForConfig函数根据传入的rest.config对象创建一个Clientset对象,此对象可以操作CoreV1()方法。
其结构体具体参数如下所示:
Clientset结构体实现了以上结构定义的所有方法。源码地址:k8s.io/client-go/kubernetes/clientset.go
因为Clientset可使用其中任意函数调用,如获取Pod列表。
在创建Clientset对象时,Clientset 中的变量coreV1也被一起初始化创建。即创建了CoreV1Client对象。
如下所示:
CoreV1Interface中包含了各种kubernetes对象的调用接口,例如PodsGetter是对kubernetes中pod对象增删改查操作的接口。ServicesGetter是对service对象的操作的接口。
CoreV1Client结构体实现了CoreV1Interface所有的定义函数。
PodsGetter接口中定义了Pods方法此方法返回PodInterface,这样就可以用Clients.Corev1().Pods()方法对Pod进行增删改查操作了。
调用Pods方法,再通过newPods函数创建一个Pods的对象。pods对象继承了rest.Interface接口,即最终的实现本质是RESTClient的HTTP调用。
PodInterface接口定义了Pod对象操作的所有方法。
Pod对象中继承了rest.Interface,上面提到过此client便是进行http请求调用。
以上分析了clientset.CoreV1().Pods("").List(metav1.ListOptions{})对pod资源获取的过程,最终是调用RESTClient的方法实现。
在CoreV1Client对象创建的时候也根据config对象调用est.RESTClientFor(config)函数创建了rest client对象。在创建Pod时将CoreV1Client对象的restClient赋值给Pod的client。
此接口定义了http请求的方法。
通过以上实现可以看出对着的接口调用都转到了Verb方法的调用。Verb方法通过传参调用NewRequest函数最终执行了一次http请求操作。
可以看到NewRequest最终将参数组成http请求参数进行了http请求调用。至此clientset.CoreV1().Pods("").List(metav1.ListOptions{})调用完成,最终将结果返回。
client-go对kubernetes资源对象的调用操作,需要先获取kubernetes的配置信息,即$HOME/.kube/config。(master节点)
具体流程如下图所示:
小白想学习go语言,哪位有教程?
如果你想每一步走得扎实,那么我的建议如下:
对一名从未接触过程序开发的小白来说,首先得足够了解计算机,至少你得知道你写的代码在计算机内部是如何运行的,你的数据是如何通过网络传输,《微机原理与接口技术》和《TCP/IP详解》(三卷)是很好的学习入门 之选,同时也是很好的参考手册
一切准备就绪,开始写你的第一个程序,建议选C语言,基本的数据结构、指针、函数、循环、条件判断、手动GC等都上手试一遍,做到了然于胸,信手拈来
进入正题,学习Go语言,你会发现,换汤不换药,程序的构成无非那么几类,当然Go会有自己的特性,比如slice、goroutine、channel等,当然这一切得基于go开发环境
至于教程,最合适的莫过于官方文档,老老实实看完,别太在意网上的各种项目实战,先学会走路,再学跑
最重要的一点:纸上得来终觉浅,绝知此事要躬行,多敲敲代码,熟能生巧,happy coding!
Go编程技巧--io.Reader/Writer
Go 原生的 pkg 中有一些核心的 interface ,其中 io.Reader/Writer 是比较常用的接口。很多原生的结构都围绕这个系列的接口展开,在实际的开发过程中,你会发现通过这个接口可以在多种不同的io类型之间进行过渡和转化。本文结合实际场景来总结一番。
围绕 io.Reader/Writer ,有几个常用的实现:
这些实现对于初学者来说其实比较难去记忆,在遇到实际问题的时候更是一脸蒙圈,不知如何是好。下面用实际的场景来举例
encoding/base64 包中:
这个用来做 base64 编码,但是仔细观察发现,它需要一个io.Writer作为输出目标,并用返回的 WriteCloser 的Write方法将结果写入目标,下面是Go官方文档的例子
这个例子是将结果写入到 Stdout ,如果我们希望得到一个字符串呢?观察上面的图,不然发现可以用bytes.Buffer作为目标 io.Writer :
这种场景经常用在基于字节的协议上,比如有一个具有固定长度的结构:
通过一个 []byte 来反序列化得到这个 Protocol ,一种思路是遍历这个 []byte ,然后逐一赋值。其实在 encoding/binary 包中有个方便的方法:
这个方法从一个 io.Reader 中读取字节,并已 order 指定的端模式,来给填充 data (data需要是fixed-sized的结构或者类型)。要用到这个方法首先要有一个 io.Reader ,从上面的图中不难发现,我们可以这么写:
换句话说,我们将一个 []byte 转成了一个 io.Reader 。
反过来,我们需要将 Protocol 序列化得到 []byte ,使用 encoding/binary 包中有个对应的 Write 方法:
通过将 []byte 转成一个 io.Writer 即可:
比如对于常见的基于文本行的 HTTP 协议的读取,我们需要将一个流按照行来读取。本质上,我们需要一个基于缓冲的读写机制(读一些到缓冲,然后遍历缓冲中我们关心的字节或字符)。在Go中有一个 bufio 的包可以实现带缓冲的读写:
这个ReadString方法从 io.Reader 中读取字符串,直到 delim ,就返回 delim 和之前的字符串。如果将 delim 设置为 \n ,相当于按行来读取了:
等价于
go操作mongo
BSON数据的主要类型有:A,D,E,M和Raw。其中,A是数组,D是切片,M是映射,D和M是Go原生类型。
A类型表示有序的BSON数组。
bson.A{"bar", "world", 3.14159, bson.D{{"qux", 12345}}}
D类型表示包含有序元素的BSON文档。这种类型应该在顺序重要的情况下使用。如果元素的顺序无关紧要,则应使用M代替。
bson.D{{"foo", "bar"}, {"hello", "world"}, {"pi", 3.14159}}
M类型表示无序的映射。
bson.M{"foo": "bar", "hello": "world", "pi": 3.14159}
E类型表示D里面的一个BSON元素。
Raw类型代表未处理的原始BSON文档和元素,Raw系列类型用于验证和检索字节切片中的元素。当要查找BSON字节而不将其解编为另一种类型时,此类型最有用。
Mongo-Driver驱动包官方文档
BSON包官方文档
mongo包官方文档
options包官方文档