gob
를 사용할 때 유형에 따라 바인딩됨을 보여줍니다. 순서에 따라 잘립니다. 다음으로 인코딩 방법을 자세히 살펴보겠습니다. " >그러나 디코딩 중에도 구문 분석이 가능합니다. 이는 gob
를 사용할 때 유형에 따라 바인딩됨을 보여줍니다. 순서에 따라 잘립니다. 다음으로 인코딩 방법을 자세히 살펴보겠습니다.
golang의 직렬화 방법은 무엇입니까?
Golang 직렬화 방법은 다음과 같습니다. 1. Gob 패키지를 사용하여 gob 스트림을 관리합니다. Gob은 유형에 바인딩되어 있으며 더 많거나 적은 것으로 확인되면 순서에 따라 채워지거나 잘립니다. 2. json 패키지를 사용하면 직렬화 프로세스 중에 RFC 7159에 정의된 JSON 인코딩 및 디코딩을 구현할 수 있습니다. 구조의 멤버가 소문자인 경우 오류가 발생합니다. 3. Binary 패키지를 사용하면 숫자와 바이트 시퀀스 간의 간단한 변환과 varint의 인코딩 및 디코딩이 가능합니다. 4. protobuf 프로토콜을 사용하십시오.
이 튜토리얼의 운영 환경: 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}
个人认为这个例子是真的好。我们看到,结构体P
和 Q
是不同的,我们看到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
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 [{ } { }]}
P
와 Q
구조가 다르다는 것을 알 수 있습니다. 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
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
위 내용은 golang의 직렬화 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

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

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

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

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

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

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

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

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

뜨거운 주제











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

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

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

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

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

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

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

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