package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
a := []string{"1", "2", "3"}
r.GET("/protobuf", func(c *gin.Context){
data := &module.User{}
c.ProtoBuf(200, data)
})
r.Run(":8080")
}
这是将信息,user进行序列化
// ProtoBuf serializes the given struct as ProtoBuf into the response body.
//二进制话,放入response体中
func (c *Context) ProtoBuf(code int, obj interface{}) {
c.Render(code, render.ProtoBuf{Data: obj})
}
// ProtoBuf contains the given interface object.
type ProtoBuf struct {
Data interface{}//data 对应任何类型
}
// Render writes the response headers and calls render.Render to render data.
func (c *Context) Render(code int, r render.Render) {
c.Status(code)
if !bodyAllowedForStatus(code) {
r.WriteContentType(c.Writer)
c.Writer.WriteHeaderNow()
return
}
if err := r.Render(c.Writer); err != nil {
panic(err)
}
}
调用Render()函数,render.ProtoBuf{Data: obj}结构体为render.Render类型,原因在于它实现了Render的接口
// Render interface is to be implemented by JSON, XML, HTML, YAML and so on.
type Render interface {
// Render writes data with custom ContentType.
//这个通用的方法
Render(http.ResponseWriter) error
// WriteContentType writes custom ContentType.
WriteContentType(w http.ResponseWriter)
}
JSON, XML, HTML, YAML都是通过实现其接口来实现的,看一下具体的实现方法
// Render (ProtoBuf) marshals the given interface object and writes data with custom ContentType.
func (r ProtoBuf) Render(w http.ResponseWriter) error {
r.WriteContentType(w)
//将data信息通过Marshal方法进行序列化
bytes, err := proto.Marshal(r.Data.(proto.Message))
if err != nil {
return err
}
_, err = w.Write(bytes)
return err
}
// WriteContentType (ProtoBuf) writes ProtoBuf ContentType.
func (r ProtoBuf) WriteContentType(w http.ResponseWriter) {
writeContentType(w, protobufContentType)
}
protobuf定义十分简单,就只有一个Data字段,通过上述方法序列化到http.ResponseWriter
2.反序列化
package main
import (
"fmt"
"github.com/golang/protobuf/proto"
"io/ioutil"
"net/http"
)
func main() {
//客户端发出请求,接收数据
resp, err := http.Get("http://localhost:8080/protobuf")
if err != nil {
fmt.Println(err)
}else {
defer resp.Body.Close()
//读出数据,返回为byte[]
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err)
}else {
//对应protobuf形成的结构体
user := &module.User{}
//反序列化
proto.UnmarshalMerge(body, user)
fmt.Println(*user)
}
}
}