목차
1. bytes.Buffer 类型" >1. bytes.Buffer 类型
2. Encode 编码" >2. Encode 编码
3. Decode 解码" >3. Decode 解码
序列化方式–json" >序列化方式–json
注意" >注意
그러나 디코딩 중에도 구문 분석이 가능합니다. 이는 gob를 사용할 때 유형에 따라 바인딩됨을 보여줍니다. 순서에 따라 잘립니다. 다음으로 인코딩 방법을 자세히 살펴보겠습니다. " >그러나 디코딩 중에도 구문 분석이 가능합니다. 이는 gob를 사용할 때 유형에 따라 바인딩됨을 보여줍니다. 순서에 따라 잘립니다. 다음으로 인코딩 방법을 자세히 살펴보겠습니다.
🎜 🎜Note🎜" >🎜 🎜Note🎜
序列化方式–Binary" >序列化方式–Binary
백엔드 개발 Golang golang의 직렬화 방법은 무엇입니까?

golang의 직렬화 방법은 무엇입니까?

Jan 04, 2023 pm 07:33 PM
golang 언어로 가다 직렬화

Golang 직렬화 방법은 다음과 같습니다. 1. Gob 패키지를 사용하여 gob 스트림을 관리합니다. Gob은 유형에 바인딩되어 있으며 더 많거나 적은 것으로 확인되면 순서에 따라 채워지거나 잘립니다. 2. json 패키지를 사용하면 직렬화 프로세스 중에 RFC 7159에 정의된 JSON 인코딩 및 디코딩을 구현할 수 있습니다. 구조의 멤버가 소문자인 경우 오류가 발생합니다. 3. Binary 패키지를 사용하면 숫자와 바이트 시퀀스 간의 간단한 변환과 varint의 인코딩 및 디코딩이 가능합니다. 4. protobuf 프로토콜을 사용하십시오.

golang의 직렬화 방법은 무엇입니까?

이 튜토리얼의 운영 환경: Windows 7 시스템, GO 버전 1.18, Dell G3 컴퓨터.

프로그래밍 과정에서 우리는 항상 데이터 개체를 네트워크를 통해 전송하거나 파일에 저장하는 문제에 직면해야 하며, 이를 위해서는 인코딩 및 디코딩 작업이 필요합니다.

현재 인코딩 형식은 json, XML, Gob, Google 프로토콜 버퍼 등 다양합니다. Go 언어에서는 어떻게 데이터를 이런 방식으로 인코딩하고 디코딩할 수 있나요?

직렬화 및 역직렬화 정의

직렬화(Serialization)는 객체의 상태 정보를 저장하거나 전송할 수 있는 형식으로 변환하는 프로세스입니다. 직렬화 중에 객체는 현재 상태를 임시 또는 영구 저장소에 씁니다.

차례로 저장 영역에서 변수를 다시 읽어서 객체를 다시 생성하는데, 이것이 deserialization입니다.

Go 언어에서 encoding 패키지는 이러한 유형의 직렬화 인코딩 및 디코딩 문제를 처리하도록 특별히 설계되었습니다.

직렬화 모드 - Gob

gob 패키지는 gob 스트림, 즉 인코더(송신자)와 디코더(수신자) 간에 교환되는 바이너리 값을 관리합니다. 일반적인 용도는 "net/rpc" 패키지에 사용되는 gobs 스트림과 같은 원격 프로시저 호출(RPC)의 매개변수와 결과를 전송하는 것입니다. gob 包管理 gob 流–编码器(发送器)和解码器(接收器)之间交换的二进制值。一个典型的用途是传输远程过程调用(RPCs)的参数和结果,如 "net/rpc "包中就使用了gobs 流。

具体可以参考文档:https://docs.studygolang.com/pkg/encoding/gob/

他的官网给出了一个示例:

package main

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

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

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

// This example shows the basic usage of the package: Create an encoder,
// transmit some values, receive them with a decoder.
func main() {
	// Initialize the encoder and decoder. Normally enc and dec would be
	// bound to network connections and the encoder and decoder would
	// run in different processes.
	var network bytes.Buffer        // Stand-in for a network connection  //Buffer是具有Read和Write方法的可变大小的字节缓冲区。
	enc := gob.NewEncoder(&network) // Will write to network.
	dec := gob.NewDecoder(&network) // Will read from network.

	// Encode (send) some values.
	err := enc.Encode(P{3, 4, 5, "Pythagoras"})
	if err != nil {
		log.Fatal("encode error:", err)
	}
	err = enc.Encode(P{1782, 1841, 1922, "Treehouse"})
	if err != nil {
		log.Fatal("encode error:", err)
	}

	// Decode (receive) and print the values.
	var q Q
	err = dec.Decode(&q)
	if err != nil {
		log.Fatal("decode error 1:", err)
	}
	fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y)
	err = dec.Decode(&q)
	if err != nil {
		log.Fatal("decode error 2:", err)
	}
	fmt.Printf("%q: {%d, %d}\n", q.Name, *q.X, *q.Y)

}
로그인 후 복사

运行结果是:

"Pythagoras": {3, 4}
"Treehouse": {1782, 1841}
로그인 후 복사

个人认为这个例子是真的好。我们看到,结构体PQ 是不同的,我们看到Q 少了一个 Z 变量。

但是,在解码的时候,仍然能解析得出来,这说明,使用 gob 时,是根据类型绑定的,如果发现多了或者少了,会依据顺序填充或者截断。

接下来,我们详情说说怎么编码吧:

1. bytes.Buffer 类型

首先,我们需要定义一个 bytes.Buffer 类型,用来承接需要序列化的结构体,这个类型是这样的:

// A Buffer is a variable-sized buffer of bytes with Read and Write methods.(Buffer是具有Read和Write方法的可变大小的字节缓冲区)
// The zero value for Buffer is an empty buffer ready to use.
type Buffer struct {
	buf      []byte // contents are the bytes buf[off : len(buf)]
	off      int    // read at &buf[off], write at &buf[len(buf)]
	lastRead readOp // last read operation, so that Unread* can work correctly.
}
로그인 후 복사

使用上面的例子,可以看到输出是:

"Pythagoras": {3, 4} ==>
{[42 255 129 3 1 1 1 80 1 255 130 0 1 4 1 1 88 1 4 0 1 1 89 1 4 0 1 1 90 1 4 0 1 4 78 97 109 101 1 12 0 0 0 21 255 130 1 6 1 8 1 10 1 10 80 121 116 104 97 103 111 114 97 115 0] 0 0}
로그인 후 복사

可以看到,Buffer 里,是二进制数(一个字节8个bit,最高255)

2. Encode 编码

之后,对需要编码序列化的结构体进行编码:

enc := gob.NewEncoder(&network) // Will write to network.
// Encode (send) some values.
if err := enc.Encode(P{3, 4, 5, "Pythagoras"}); err != nil {
	log.Fatal("encode error:", err)
}
로그인 후 복사

这里,首先是要获得 *Encoder 对象,获得对象后,利用 *Encoder 对象的方法 Encode 进行编码。

这里,需要注意的是,Encode 如果是网络编程的,其实是可以直接发送消息给对方的,而不必进行 socket 的send 操作。

比如:在 srever 端有代码:

func main() {
	l, err := net.Listen("tcp", "127.0.0.1:8000")  //监听端口
	if err != nil {
		log.Fatal("net Listen() error is ", err)
	}

	p := P{
		1, 2, 3,
		"name"}

	conn, err := l.Accept()
	if err != nil {
		log.Fatal("net Accept() error is ", err)
	}
	defer func() { _ = conn.Close() }()
	//参数是conn 时,即可发出
	enc := gob.NewEncoder(conn)
	if err = enc.Encode(p); err != nil {  //发生结构体数据
		log.Fatal("enc Encode() error is ", err)
	}
}
로그인 후 복사

在客户端client有:

func main() {
	conn,err := net.Dial("tcp","127.0.0.1:8000")
	if err != nil {
		log.Fatal("net Dial() error is ", err)
	}
	defer func() { _ = conn.Close() }()
	/**
	type Q struct {
		X, Y int
		Name string
	}
	 */
	var q Q
	dec := gob.NewDecoder(conn)
	if err = dec.Decode(&q); err != nil {
		log.Fatal("enc Encode() error is ", err)
	}
	fmt.Println(q)
}
로그인 후 복사

输出:

{1 2 name}
로그인 후 복사

3. Decode 解码

最后,对其解码的步骤为:

dec := gob.NewDecoder(&network) // Will read from network.
if err = dec.Decode(&q);err != nil {
	log.Fatal("decode error 2:", err)
}
로그인 후 복사

序列化方式–json

json 包实现了 RFC 7159 中定义的 JSON 编码和解码。JSON和Go值之间的映射在 Marshal 和 Unmarshal 函数的文档中进行了描述。

有关此程序包的介绍,请参见“ JSON和Go”:https://www.php.cn/link/241200d15bc67211b50bd10815259e58json/

示例如下:

type Message struct {
	QQ      string
	Address string
}

type Student struct {
	Id   uint64 `json:"id"` //可以保证json字段按照规定的字段转义,而不是输出 Id
	Age  uint64 `json:"age"`
	Data []Message
}

func main() {
	m1 := Message{QQ: "123", Address: "beijing"}
	m2 := Message{QQ: "456", Address: "beijing"}
	s1 := Student{3, 19, append([]Message{}, m1, m2)}
	var buf []byte
	var err error

	if buf, err = json.Marshal(s1); err != nil {
		log.Fatal("json marshal error:", err)
	}

	fmt.Println(string(buf))

	var s2 Student
	if err = json.Unmarshal(buf, &s2); err != nil {
		log.Fatal("json unmarshal error:", err)
	}
	fmt.Println(s2)
}
//输出:
//{"id":3,"age":19,"Data":[{"QQ":"123","Address":"beijing"},{"QQ":"456","Address":"beijing"}]}
//{3 19 [{123 beijing} {456 beijing}]}
로그인 후 복사

注意

在序列化的过程中,如果结构体内的成员是小写的,则会出现错误。以上两种方式,都会出现这样的结果

我们以 json

자세한 내용은 문서를 참조하세요: https://docs.studygolang.com/pkg/encoding/gob/

그의 공식 웹사이트는 예를 제공합니다:

package main

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

type Message struct {
	qq      string
	address string
}

type Student struct {
	Id   uint64 `json:"id"` //可以保证json字段按照规定的字段转义,而不是输出 Id
	Age  uint64 `json:"age"`
	Data []Message
}

func main() {
	m1 := Message{"123", "beijing"}
	m2 := Message{"456", "beijing"}
	s1 := Student{3, 19, append([]Message{}, m1, m2)}
	var buf []byte
	var err error

	if buf, err = json.Marshal(s1); err != nil {
		log.Fatal("json marshal error:", err)
	}

	fmt.Println(string(buf))

	var s2 Student
	if err = json.Unmarshal(buf, &s2); err != nil {
		log.Fatal("json unmarshal error:", err)
	}
	fmt.Println(s2)
}
로그인 후 복사

실행 결과는:

{"id":3,"age":19,"Data":[{},{}]}
{3 19 [{ } { }]}
로그인 후 복사

개인적으로 저는 이 예가 사실이라고 생각하세요. 좋아요. PQ 구조가 다르다는 것을 알 수 있습니다. Q에는 Z 변수가 없습니다.

그러나 디코딩 중에도 구문 분석이 가능합니다. 이는 gob를 사용할 때 유형에 따라 바인딩됨을 보여줍니다. 순서에 따라 잘립니다. 다음으로 인코딩 방법을 자세히 살펴보겠습니다.

1. bytes.Buffer type

먼저 bytes.Buffer 유형은 직렬화해야 하는 구조를 받아들이는 데 사용됩니다. 이 유형은 다음과 같습니다.

type Message struct {
	qq      string
	address string
}

type Student struct {
	Id   uint64 `json:"id"` //可以保证json字段按照规定的字段转义,而不是输出 Id
	Age  uint64 `json:"age"`
	Data []Message
}

func main() {
	m1 := Message{"123", "beijing"}
	m2 := Message{"456", "beijing"}
	s1 := Student{3, 19, append([]Message{}, m1, m2)}

	var buf bytes.Buffer
	enc := gob.NewEncoder(&buf)
	if err := enc.Encode(s1); err != nil {
		log.Fatal("encode error:", err) //报错
	}
	fmt.Println(string(buf.Bytes()))
}
로그인 후 복사
위의 예를 사용하면 출력이 다음과 같은 것을 볼 수 있습니다.

2020/12/30 16:44:47 encode error:gob: type main.Message has no exported fields
로그인 후 복사
🎜볼 수 있습니다. 버퍼 는 이진수입니다(바이트당 8비트, 최대 255)🎜🎜
🎜🎜2. 인코딩 인코딩 후🎜🎜🎜에서 인코딩 및 직렬화를 수행합니다. 구조체 인코딩: 🎜
package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

func main() {
	buf := new(bytes.Buffer)
	var pi int64 = 255

	err := binary.Write(buf, binary.LittleEndian, pi)
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	fmt.Println( buf.Bytes())
}
//输出:
[255 0 0 0 0 0 0 0]
로그인 후 복사
로그인 후 복사
🎜여기서 먼저 *Encoder 객체를 구한 후 *Encoder<의 <code>Encode 메소드를 사용하세요. /code> 인코딩할 개체입니다. 🎜🎜🎜여기서, 네트워크 프로그래밍에 인코드를 사용하면 소켓 전송 작업을 수행하지 않고도 실제로 상대방에게 직접 메시지를 보낼 수 있다는 점에 유의해야 합니다. 🎜🎜🎜예: srever 측에 코드가 있습니다: 🎜
binary.Write failed: binary.Write: invalid type int
로그인 후 복사
로그인 후 복사
🎜클라이언트 측에: 🎜rrreee🎜출력: 🎜rrreee🎜
🎜🎜3. decoder🎜 🎜🎜마지막으로 디코딩하는 단계는 다음과 같습니다. 🎜rrreee🎜🎜🎜직렬화 방법 – json🎜🎜🎜json 패키지는 RFC 7159</를 구현합니다. <code>JSON 인코딩 및 디코딩은 code>에 정의되어 있습니다. JSON과 Go 값 간의 매핑은 Marshal 및 Unmarshal 함수에 대한 설명서에 설명되어 있습니다. 🎜🎜이 패키지에 대한 소개는 "JSON and Go"를 참조하세요: https://www.php.cn/link/241200d15bc67211b50bd10815259e58json/🎜🎜예는 다음과 같습니다: 🎜rrreee

🎜 🎜Note🎜

🎜직렬화 과정에서 구조체의 멤버가 소문자일 경우 오류가 발생합니다. 🎜위의 두 가지 방법은 이러한 결과를 생성합니다.🎜🎜🎜json 직렬화를 예로 들어 소문자인 경우 결과가 어떻게 될지 확인합니다. 🎜rrreee🎜출력: 🎜rrreee 🎜우리는 소문자 부분은 직렬화되지 않습니다. 즉, null 값이 됩니다. 🎜🎜오류를 보고하지는 않지만 분명히 우리가 보고 싶은 결과는 아닙니다. 🎜🎜🎜🎜🎜오류: gob: xxx 유형에는 내보낸 필드가 없습니다.🎜🎜🎜오류를 보고하는 예를 살펴보겠습니다.🎜rrreee🎜이 코드는 오류를 보고합니다.🎜rrreee🎜🎜대문자 사용을 기억하세요. 구조가 매우 민감합니다! ! ! 🎜🎜

序列化方式–Binary

Binary 包实现 数字字节 序列之间的简单转换以及varint的编码和解码。

通过读取和写入固定大小的值来转换数字。 固定大小的值可以是固定大小的算术类型(bool,int8,uint8,int16,float32,complex64等),也可以是仅包含固定大小值的数组或结构体。详情可参考:https://www.php.cn/link/241200d15bc67211b50bd10815259e58binary/#Write

示例:

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
)

func main() {
	buf := new(bytes.Buffer)
	var pi int64 = 255

	err := binary.Write(buf, binary.LittleEndian, pi)
	if err != nil {
		fmt.Println("binary.Write failed:", err)
	}
	fmt.Println( buf.Bytes())
}
//输出:
[255 0 0 0 0 0 0 0]
로그인 후 복사
로그인 후 복사

这里需要注意:如果序列化的类型是 int 类型的话,将会报错:

binary.Write failed: binary.Write: invalid type int
로그인 후 복사
로그인 후 복사

而且,序列化的值是空的。

这是由于,他在前面已经解释清楚了,只能序列化固定大小的类型(bool,int8,uint8,int16,float32,complex64…),或者是结构体和固定大小的数组。

其他序列化方法

当然,go语言还有其他的序列化方法,如 protobuf 协议,参考:https://geektutu.com/post/quick-go-protobuf.html

【相关推荐:Go视频教程编程教学

위 내용은 golang의 직렬화 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Golang을 사용하여 파일을 안전하게 읽고 쓰는 방법은 무엇입니까? Golang을 사용하여 파일을 안전하게 읽고 쓰는 방법은 무엇입니까? Jun 06, 2024 pm 05:14 PM

Go에서는 안전하게 파일을 읽고 쓰는 것이 중요합니다. 지침은 다음과 같습니다. 파일 권한 확인 지연을 사용하여 파일 닫기 파일 경로 유효성 검사 컨텍스트 시간 초과 사용 다음 지침을 따르면 데이터 보안과 애플리케이션의 견고성이 보장됩니다.

Golang 데이터베이스 연결을 위한 연결 풀을 구성하는 방법은 무엇입니까? Golang 데이터베이스 연결을 위한 연결 풀을 구성하는 방법은 무엇입니까? Jun 06, 2024 am 11:21 AM

Go 데이터베이스 연결을 위한 연결 풀링을 구성하는 방법은 무엇입니까? 데이터베이스 연결을 생성하려면 데이터베이스/sql 패키지의 DB 유형을 사용하고, 최대 동시 연결 수를 제어하려면 MaxIdleConns를 설정하고, 연결의 최대 수명 주기를 제어하려면 ConnMaxLifetime을 설정하세요.

Golang과 C++의 유사점과 차이점 Golang과 C++의 유사점과 차이점 Jun 05, 2024 pm 06:12 PM

Golang과 C++는 각각 가비지 수집 및 수동 메모리 관리 프로그래밍 언어로, 구문과 유형 시스템이 다릅니다. Golang은 Goroutine을 통해 동시 프로그래밍을 구현하고, C++는 스레드를 통해 이를 구현합니다. Golang 메모리 관리는 간단하고 C++는 더 강력한 성능을 제공합니다. 실제적인 경우 Golang 코드는 더 간결하며 C++는 확실한 성능 이점을 제공합니다.

golang 프레임워크 아키텍처의 학습 곡선은 얼마나 가파르나요? golang 프레임워크 아키텍처의 학습 곡선은 얼마나 가파르나요? Jun 05, 2024 pm 06:59 PM

Go 프레임워크 아키텍처의 학습 곡선은 Go 언어 및 백엔드 개발에 대한 친숙도와 선택한 프레임워크의 복잡성, 즉 Go 언어의 기본 사항에 대한 올바른 이해에 따라 달라집니다. 백엔드 개발 경험이 있으면 도움이 됩니다. 다양한 복잡성의 프레임워크는 다양한 학습 곡선으로 이어집니다.

Golang의 목록에서 임의의 요소를 생성하는 방법은 무엇입니까? Golang의 목록에서 임의의 요소를 생성하는 방법은 무엇입니까? Jun 05, 2024 pm 04:28 PM

Golang에서 목록의 임의 요소를 생성하는 방법: rand.Intn(len(list))을 사용하여 목록의 길이 범위 내에서 임의의 정수를 생성합니다. 정수를 인덱스로 사용하여 목록에서 해당 요소를 가져옵니다.

golang 프레임워크의 장점과 단점 비교 golang 프레임워크의 장점과 단점 비교 Jun 05, 2024 pm 09:32 PM

Go 프레임워크는 높은 성능과 동시성 장점으로 인해 두각을 나타냅니다. 그러나 상대적으로 새로운 프레임워크, 작은 개발자 생태계, 일부 기능 부족 등 몇 가지 단점도 있습니다. 또한 빠른 변화와 학습 곡선은 프레임워크마다 다를 수 있습니다. Gin 프레임워크는 효율적인 라우팅, 내장된 JSON 지원 및 강력한 오류 처리로 인해 RESTful API를 구축하는 데 널리 사용됩니다.

Golang 프레임워크의 오류 처리에 대한 모범 사례는 무엇입니까? Golang 프레임워크의 오류 처리에 대한 모범 사례는 무엇입니까? Jun 05, 2024 pm 10:39 PM

모범 사례: 잘 정의된 오류 유형(오류 패키지)을 사용하여 사용자 정의 오류 생성 자세한 내용 제공 오류를 적절하게 기록 오류를 올바르게 전파하고 컨텍스트를 추가하기 위해 필요에 따라 오류를 숨기거나 억제하지 않음

golang 프레임워크의 장점은 무엇인가요? golang 프레임워크의 장점은 무엇인가요? Jun 06, 2024 am 10:26 AM

Golang 프레임워크의 장점 Golang은 마이크로서비스 및 분산 시스템에 특히 적합한 고성능 동시 프로그래밍 언어입니다. Golang 프레임워크는 미리 만들어진 구성 요소 및 도구 세트를 제공하여 이러한 애플리케이션을 더 쉽게 개발할 수 있도록 해줍니다. 다음은 Golang 프레임워크의 주요 장점 중 일부입니다. 1. 고성능 및 동시성: Golang 자체는 고성능 및 동시성으로 유명합니다. 코드 동시 실행을 허용하는 경량 스레딩 메커니즘인 고루틴을 사용하여 애플리케이션 처리량과 응답성을 향상시킵니다. 2. 모듈성 및 재사용성: Golang 프레임워크는 모듈성과 재사용 가능한 코드를 장려합니다. 애플리케이션을 독립된 모듈로 분리하면 코드를 쉽게 유지 관리하고 업데이트할 수 있습니다.

See all articles