设为首页 收藏本站
查看: 1031|回复: 0

[经验分享] golang数据传输格式

[复制链接]

尚未签到

发表于 2018-9-20 11:50:16 | 显示全部楼层 |阅读模式
  golang数据传输格式-序列化与反序列化
  作者:尹正杰
  版权声明:原创作品,谢绝转载!否则将追究法律责任。
  想必计算机专业毕业的小伙伴应该都知道数据想要持久化存储,必须将其存在I/O设备里面,这些I/O设备可以是光盘,U盘,机械硬盘,移动硬盘等等。那么这些数据是以哪种方式进程存取的呢?这就是我们聊的数据传输格式。
  数据格式(data format)是描述数据保存在文件或记录中的规则。可以是字符形式的文本格式,或二进制数据形式的压缩格式。字符形式的文本格式占用的存贮空间多但透明度高,二进制数形式的压缩格式占用的存贮空间少但缺少透明度。数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。
  数据结构往往同高效的检索算法和索引技术有关。[1] 数据结构要在网络中传输或保存到文件,就必须对其编码和解码;目前存在很多编码格式:JSON,XML,gob,Google 缓冲协议等等。Go 语言支持所有这些编码格式。不过本篇博客将讨论前三种格式。
  一.XML
  XML作为一种数据交换和信息传递的格式已经十分普及。而随着 Web服务日益广泛的应用,现在XML在日常的开发工作中也扮演了愈发重要的角色。如同 json 包一样,也有 Marshal() 和 UnMarshal() 从 XML 中编码和解码数据;但这个更通用,可以从文件中读取和写入(或者任何实现了 io.Reader 和 io.Writer 接口的类型)和 JSON 的方式一样,XML 数据可以序列化为结构,或者从结构反序列化为 XML 数据;
  接下来我们将对“yinzhengjie.xml”文件进行反序列化,其文件内容如下:
  

         
                   
  
     yinzhengjie   
  
     尹正杰
  
                 
  

  1.Xml数据格式的反序列化
  

/*  
#!/usr/bin/env gorun
  
@author :yinzhengjie
  
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  
EMAIL:y1053419035@qq.com
  
*/
  

  
package main
  

  
import (
  
     "encoding/xml"
  
     "io/ioutil"
  
     "log"
  
     "fmt"
  
)
  

  
var (
  
     InputFile = "E:\\Code\\Golang\\Golang_Program\\数据格式进阶\\yinzhengjie.xml"
  
)
  

  

  
type RootElement struct {                                            //这是定义根元素的,我们需要做的就是讲XML数据的结构先定义出来,就是为了方便主函数一会直接通过这个结构去读取数据。
  
     XMLName        xml.Name         `xml:"UserInformation"`     //这个我们指定XML的根元素,我们也可以叫它最外层标签。
  
     ResourceString []ChildElement `xml:"string"`                //上面是指定父标签的话,这个应该就不用多做解释吧,当然是子标签了啦。如果你的子表情有多个属性的,或是有多个同类型的标签的话,就可以用切片来存储。
  
}
  

  
type ChildElement struct {                    //这个结构体是定义子元素的结构的。
  
     XMLName    xml.Name `xml:"string"`        //注意,这里是我们的子元素的一级标签,因此该标签的名称必须填写正确,不然反序列化的时候就会报错。
  
     StringName string   `xml:"age,attr"`        //这个是定义,一级标签的属性的,我们需要用attr来进行表示,于此同时,我们还需要输入属性的关键字“age”
  
     InnerText  string   `xml:",innerxml"`            //这行就是定义标签里面的具体内容经的,对了,其中关键字“,innerxml”里的逗号不要忘记哟。
  
}
  

  
func main() {
  
     GolangXml, err := ioutil.ReadFile(InputFile)    //我们把数据一次性读取到一个切片中。
  
     if err != nil {
  
         log.Fatal(err)
  
     }
  

  
     var result RootElement
  
     fmt.Printf("序列化之前GolangXml = [%v]\n",result)
  
     err = xml.Unmarshal(GolangXml, &result)            //然后对数据进行反序列化。
  
     if err != nil {
  
         log.Fatal(err)
  
     }
  
     fmt.Printf("序列化之后GolangXml = [%v]\n",result)
  
     fmt.Println(result.ResourceString)
  
}
  

  

  

  
#以上代码执行结果如下:
  
序列化之前GolangXml = [{{ } []}]
  
序列化之后GolangXml = [{{ UserInformation} [{{ string} 18 yinzhengjie} {{ string} 20 尹正杰}]}]
  
[{{ string} 18 yinzhengjie} {{ string} 20 尹正杰}]
  

  2.Xml数据格式的序列化
  

/*  
#!/usr/bin/env gorun
  
@author :yinzhengjie
  
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  
EMAIL:y1053419035@qq.com
  
*/
  

  
package main
  

  
import (
  
     "encoding/xml"
  
     "io/ioutil"
  
     "log"
  
     "fmt"
  
     "strings"
  
     "os"
  
)
  

  
var (
  
     InputFile = "E:\\Code\\Golang\\Golang_Program\\数据格式进阶\\yinzhengjie.xml"
  
     OutputFile = "E:\\Code\\Golang\\Golang_Program\\数据格式进阶\\yinzhengjie.xml.bak"
  
)
  

  

  
type RootElement struct {                                            //这是定义根元素的,我们需要做的就是讲XML数据的结构先定义出来,就是为了方便主函数一会直接通过这个结构去读取数据。
  
     XMLName        xml.Name         `xml:"UserInformation"`     //这个我们指定XML的根元素,我们也可以叫它最外层标签。
  
     ResourceString []ChildElement `xml:"string"`                //上面是指定父标签的话,这个应该就不用多做解释吧,当然是子标签了啦。如果你的子表情有多个属性的,或是有多个同类型的标签的话,就可以用切片来存储。
  
}
  

  
type ChildElement struct {                    //这个结构体是定义子元素的结构的。
  
     XMLName    xml.Name `xml:"string"`        //注意,这里是我们的子元素的一级标签,因此该标签的名称必须填写正确,不然反序列化的时候就会报错。
  
     StringName string   `xml:"age,attr"`        //这个是定义,一级标签的属性的,我们需要用attr来进行表示,于此同时,我们还需要输入属性的关键字“age”
  
     InnerText  string   `xml:",innerxml"`            //这行就是定义标签里面的具体内容经的,对了,其中关键字“,innerxml”里的逗号不要忘记哟。
  
}
  

  
func main() {
  
     GolangXml, err := ioutil.ReadFile(InputFile)    //我们把数据一次性读取到一个切片中。
  
     if err != nil {
  
         log.Fatal(err)
  
     }
  

  
     var result RootElement
  
     err = xml.Unmarshal(GolangXml, &result)            //然后对数据进行反序列化。
  
     if err != nil {
  
         log.Fatal(err)
  
     }
  
     for key,value := range result.ResourceString{
  
         if strings.EqualFold(value.StringName,"18") {  //只修改属性值为"18"节点的内部文本innerText
  
             result.ResourceString[key].InnerText = "666666666666666"    //注意修改的不是value对象,而是直接使用result中的真实对象
  
             fmt.Println("内容修改完毕!")
  
         }
  
     }
  
     XmlOutput,err := xml.MarshalIndent(result,"","")    //保存修改后的内容
  
     if err == nil {
  
         HeaderBytes := []byte(xml.Header)                          //加入XML头信息
  
         XmlData := append(HeaderBytes,XmlOutput...)                //拼接XML头和实际XML内容
  
         ioutil.WriteFile(OutputFile,XmlData,os.ModeAppend)        //写入文件
  
         fmt.Println(string(XmlData))
  
         fmt.Println("文件写入成功!")
  
     }else {
  
         fmt.Println(err)
  
     }
  
}
  

  

  

  
#以上代码执行结果如下:
  
内容修改完毕!
  

  
666666666666666尹正杰
  
文件写入成功!
  

  执行以上代码之后,会生成一个新的文件,即“yinzhengjie.xml.bak”文件。其内容如下:
  

  
666666666666666尹正杰
  

  更多关于学习XML知识的话,我推荐两个学习的网站给大家:
  a>.http://www.xml.org/
  b>.http://www.w3school.com.cn/xml/
  二.JSON
  JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。人类阅读和写作很容易。机器解析和生成很容易。它基于JavaScript编程语言的一个子集 , 标准ECMA-262第3版 - 1999年12月。JSON是完全独立于语言的文本格式,但是使用C语言家族的程序员熟悉的约定,包括C,C ++,C#,Java,JavaScript,Perl,Python等等。这些属性使JSON成为理想的数据交换语言。
  1.Json数据格式的序列化
  在golang语言中,我们用json.Marshal() 进行序列化。json.Marshal() 的函数签名是 func Marshal(v interface{}) ([]byte, error)。出于安全考虑,在 web 应用中最好使用 json.MarshalforHTML() 函数,其对数据执行HTML转码,所以文本可以被安全地嵌在 HTML  标签中。序列化是在内存中把数据转换成指定格式(data -> string),反之亦然(string -> data structure)编码也是一样的,只是输出一个数据流(实现了 io.Writer 接口);解码是从一个数据流(实现了io.Reader)输出到一个数据结构。
  JSON 与 Go 类型对应如下:
  a>.bool 对应 JSON 的 booleans;
  b>.float64 对应 JSON 的 numbers;
  c>.string 对应 JSON 的 strings;
  d>.nil 对应 JSON 的 null;
  不是所有的数据都可以编码为 JSON 类型:只有验证通过的数据结构才能被编码:
  a>.JSON 对象只支持字符串类型的 key;要编码一个 Go map 类型,map 必须是 map[string]T(T是json 包中支持的任何类型);
  b>.Channel,复杂类型和函数类型不能被编码;
  c>.不支持循环数据结构;它将引起序列化进入一个无限循环;
  d>.指针可以被编码,实际上是对指针指向的值进行编码(或者指针是 nil);
  Go 语言的 json 包可以让你在程序中方便的读取和写入 JSON 数据。接下来我们一起看一下golang是如何使用json包的:
  

/*  
#!/usr/bin/env gorun
  
@author :yinzhengjie
  
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  
EMAIL:y1053419035@qq.com
  
*/
  

  
package main
  

  
import (
  
     "encoding/json"
  
     "fmt"
  
     "log"
  
     "os"
  
)
  

  
var (
  
     OutputFile = "E:\\Code\\Golang\\Golang_Program\\数据格式进阶\\yinzhengjie.json"
  
)
  

  
type TenScenicSpots struct {    //定义10个景区的名称。
  
     FirstScenic string
  
     SecondScenic string
  
     ThirdScenic string
  
     FourthScenic string
  
     FifrhScenic    string
  
     SixthScenic string
  
     SeventhScenic string
  
     EigthtScenic string
  
     NinthScenic string
  
     TenthScenic string
  
}
  

  
type TouristInformation struct {    //定义游客信息
  
     VisitorName string                //游客姓名
  
     Nationality string                //游客国籍
  
     City string                        //想要去的城市
  
     ScenicSpot []*TenScenicSpots    //想要去看的景区
  

  
}
  

  
func main() {
  
     ChaoyangDistrict := &TenScenicSpots{"中华名族园","北京奥林匹克公园","国家体育馆","中国科学技术官","奥林匹克公园网球场","蟹岛绿色生态农庄","国家游泳中心(水立方)","中国紫檀博物馆","北京欢乐谷","元大都城"}
  
     DaxingDistrict := &TenScenicSpots{ "北京野生动物园","男孩子麋鹿苑","中华文化园","留民营生态农场","中国印刷博物馆","北普陀影视城","大兴滨河森林公园","呀路古热带植物园","庞各庄万亩梨园","西黄垈村"}
  
     District := TouristInformation{"尹正杰", "中国", "北京", []*TenScenicSpots{ChaoyangDistrict, DaxingDistrict}}
  
     GolangJson, err := json.Marshal(District) //这个步骤就是序列化的过程。json.Marshal方法会返回一个字节数组,即GolangJson,与此同时,District已经是JSON格式的啦。
  
     if err != nil {
  
         log.Fatal("序列化报错是:%s",err)
  
     }
  
     fmt.Printf("JSON format: %s", GolangJson)
  

  
     file, _ := os.OpenFile(OutputFile, os.O_CREATE|os.O_WRONLY, 0)
  
     defer file.Close()
  
     Write := json.NewEncoder(file)  //创建一个编码器。
  
     err = Write.Encode(District)    //由于District已经被json.Marshal方法处理过了,所以我们直接把JSON格式的District传给Write写入器,调用该写入器的Encode方法可以对JSON格式的数据进行编码。如果顺利的话,我们会得到一个nil参数,否则我们会得到编码的错误信息。
  
     if err != nil {
  
         log.Println("Error in encoding json")
  
     }
  
}
  

  

  

  

  
#以上代码执行结果如下:
  
JSON format: {"VisitorName":"尹正杰","Nationality":"中国","City":"北京","ScenicSpot":[{"FirstScenic":"中华名族园","SecondScenic":"北京奥林匹克公园","ThirdScenic":"国家体育馆","FourthScenic":"中国科学技术官","FifrhScenic":"奥林匹克公园网球场","SixthScenic":"蟹岛绿色生态农庄","SeventhScenic":"国家游泳中心(水立方)","EigthtScenic":"中国紫檀博物馆","NinthScenic":"北京欢乐谷","TenthScenic":"元大都城"},{"FirstScenic":"北京野生动物园","SecondScenic":"男孩子麋鹿苑","ThirdScenic":"中华文化园","FourthScenic":"留民营生态农场","FifrhScenic":"中国印刷博物馆","SixthScenic":"北普陀影视城","SeventhScenic":"大兴滨河森林公园","EigthtScenic":"呀路古热带植物园","NinthScenic":"庞各庄万亩梨园","TenthScenic":"西黄垈村"}]}
  

  2.Json数据格式的反序列化    
  如果我们事先知道 JSON 数据,我们可以定义一个适当的结构并对 JSON 数据反序列化。我们上面做序列化的时候创建了一个“yinzhengjie.json”的文件,里面的数据结果我们是心知肚明的,因此,接下来反序列化就是一件很Easy的事情啦。
  

/*  
#!/usr/bin/env gorun
  
@author :yinzhengjie
  
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  
EMAIL:y1053419035@qq.com
  
*/
  

  
package main
  

  

  
import (
  
     "encoding/json"
  
     "fmt"
  
     "log"
  
     "io/ioutil"
  
)
  

  
var (
  
     InputFile = "E:\\Code\\Golang\\Golang_Program\\数据格式进阶\\yinzhengjie.json"
  
)
  

  
type TenScenicSpots struct {    //定义10个景区的名称。
  
     FirstScenic string
  
     SecondScenic string
  
     ThirdScenic string
  
     FourthScenic string
  
     FifrhScenic    string
  
     SixthScenic string
  
     SeventhScenic string
  
     EigthtScenic string
  
     NinthScenic string
  
     TenthScenic string
  
}
  

  
type TouristInformation struct {    //定义游客信息
  
     VisitorName string                //游客姓名
  
     Nationality string                //游客国籍
  
     City string                        //想要去的城市
  
     ScenicSpot []*TenScenicSpots    //想要去看的景区
  

  
}
  

  
func main() {
  
     var GolangJson   TouristInformation        //定义反序列化JSON的格式
  

  
     file,err := ioutil.ReadFile(InputFile)  //得到的文件是一个字节切片哟
  
     if err != nil {
  
         log.Println(err)
  
     }
  

  
     err = json.Unmarshal(file,&GolangJson)  //将得到的字节进行反序列化
  
     if err != nil {
  
         log.Fatal("反序列化报错啦:%s",err)
  
     }
  

  
     fmt.Printf("JSON format: %v\n", GolangJson) //将反序列化的文件打印出来。
  
     fmt.Println(GolangJson.City)
  
     fmt.Println(GolangJson.ScenicSpot[1])
  
}
  

  

  

  
#以上代码执行结果如下:
  
JSON format: {尹正杰 中国 北京 [0xc042050140 0xc042050280]}
  
北京
  
&{北京野生动物园 男孩子麋鹿苑 中华文化园 留民营生态农场 中国印刷博物馆 北普陀影视城 大兴滨河森林公园 呀路古热带植物园 庞各庄万亩梨园 西黄垈村}
  

  更多关于学习XML知识的话,我推荐两个学习的网站给大家:
  a>.http://www.json.org/
  b>.http://www.w3school.com.cn/json/
  三.Gob
  Gob 是 Go 自己的以二进制形式序列化和反序列化程序数据的格式;可以在 encoding 包中找到。这种格式的数据简称为 Gob (即 Go binary 的缩写)。类似于 Python 的 "pickle" 和 Java 的"Serialization"。
  Gob 通常用于远程方法调用参数和结果的传输,以及应用程序和机器之间的数据传输。 它和 JSON 或 XML 有什么不同呢?Gob 特定地用于纯 Go 的环境中,例如,两个用 Go 写的服务之间的通信。这样的话服务可以被实现得更加高效和优化。 Gob 不是可外部定义,语言无关的编码方式。因此它的首选格式是二进制,而不是像 JSON 和 XML 那样的文本格式。 Gob 并不是一种不同于Go 的语言,而是在编码和解码过程中用到了 Go 的反射。
  Gob 文件或流是完全自描述的:里面包含的所有类型都有一个对应的描述,并且总是可以用 Go 解码,而不需要了解文件的内容。
  只有可导出的字段会被编码,零值会被忽略。在解码结构体的时候,只有同时匹配名称和可兼容类型的字段才会被解码。当源数据类型增加新字段后,Gob 解码客户端仍然可以以这种方式正常工作:解码客户端会继续识别以前存在的字段。并且还提供了很大的灵活性,比如在发送者看来,整数被编码成没有固定长度的可变长度,而忽略具体的 Go 类型。
  Golang的解码和编码就相对简单啦,就我个人而言,我对golang专有的gob格式还是那么的情有独钟。它的使用方法很简单,我们可以一起看一下它的解码和编码的过程,具体代码 如下:
  1.Gob的编码(序列化)
  

/*  
#!/usr/bin/env gorun
  
@author :yinzhengjie
  
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  
EMAIL:y1053419035@qq.com
  
*/
  

  
package main
  

  
import (
  
     "bytes"
  
     "encoding/gob"
  
     "log"
  
     "io/ioutil"
  
)
  

  
var (
  
     OutputFile = "E:\\Code\\Golang\\Golang_Program\\数据格式进阶\\yinzhengjie.gob"
  
)
  

  
type P struct {
  
     X, Y, Z int
  
     Name    string
  
}
  

  
func main() {
  
     var GolngGob bytes.Buffer
  

  
     enc := gob.NewEncoder(&GolngGob) //生成一个的编码器
  

  
     yzj := P{100, 200, 300, "Yinzhengjie"}
  
     err := enc.Encode(yzj)    //编码结构体和数据
  
     if err != nil {
  
         log.Fatal("encode error:", err)
  
     }
  
     ioutil.WriteFile(OutputFile, GolngGob.Bytes(), 0644)        //我们把编码后的数据写入文件
  
}
  

  执行以上代码之后会生成一个“yinzhengjie.gob”文件,这个文件的内容是二进制编码的,因此我们用gbk编码或是utf-8编码格式直接去打开的话可能不是很理想。因此我们可以通过gob的反序列化来进行读取操作,具体代码请参考以下代码。
  2.Gob的解码(反序列化)
  

/*  
#!/usr/bin/env gorun
  
@author :yinzhengjie
  
Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
  
EMAIL:y1053419035@qq.com
  
*/
  

  
package main
  

  
import (
  
     "encoding/gob"
  
     "log"
  
     "os"
  
     "fmt"
  
)
  

  
var (
  
     InputFile = "E:\\Code\\Golang\\Golang_Program\\数据格式进阶\\yinzhengjie.gob"
  
)
  

  
type P struct {
  
     X, Y, Z int
  
     Name    string
  
}
  

  
type Q struct {
  
     X, Y,Z*int32
  
     Name string
  
}
  

  
func main() {
  
     file,err := os.Open(InputFile)
  
     dec := gob.NewDecoder(file)        //生成一个解码器
  

  
     var GolangGob Q
  
     fmt.Printf("解码前GolangGob的内容为[%v]\n",GolangGob)
  
     err = dec.Decode(&GolangGob)    //开始按照我们定义好的GolangGob结构体开始解码。
  
     if err != nil {
  
         log.Fatal("decode error:", err)
  
     }
  
     fmt.Printf("解码后GolangGob的内容为[%v]\n",GolangGob)
  

  
     fmt.Printf("详细内容为:【%d,%d,%d,%q】\n", *GolangGob.X, *GolangGob.Y, *GolangGob.Z, GolangGob.Name)    //注意传参的顺序哟!
  
}
  

  

  

  
#以上代码执行结果如下:
  
解码前GolangGob的内容为[{   }]
  
解码后GolangGob的内容为[{0xc04203c838 0xc04203c83c 0xc04203c840 Yinzhengjie}]
  
详细内容为:【100,200,300,"Yinzhengjie"】
  

  四.数据传输进阶知识-golang中的密码学
  通过网络传输的数据必须加密,以防止被 hacker(黑客)读取或篡改,并且保证发出的数据和收到的数据检验和一致。 鉴于 Go 母公司的业务,我们毫不惊讶地看到 Go 的标准库为该领域提供了超过 30 个包:
  1>.hash 包:实现了 adler32 、 crc32 、 crc64 和 fnv 校验;
  2>.crypto 包:实现了其它的 hash 算法,比如 md4 、 md5 、 sha1 等。以及完整地实现了 aes 、blowfish 、 rc4 、 rsa 、 xtea 等加密算法。
  想要了解更多关于golang加密方法的可以参考:http://www.cnblogs.com/yinzhengjie/p/7368030.html



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-598835-1-1.html 上篇帖子: golang之map数据类型 下篇帖子: 设计自用的golang日志模块
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表