Rumah  >  Artikel  >  pembangunan bahagian belakang  >  golang byte转struct

golang byte转struct

PHPz
PHPzasal
2023-05-15 09:07:361342semak imbas

Menukar tatasusunan bait kepada struct dalam Golang ialah masalah biasa yang akan dihadapi oleh ramai pembangun. Tatasusunan bait Golang sangat mudah untuk memproses data binari, tetapi untuk struktur data yang kompleks, seperti struct, pemprosesan manual diperlukan kod sedemikian panjang dan mudah ralat. Artikel ini akan memperkenalkan cara menukar tatasusunan bait kepada struct melalui Golang.

1. Penukaran melalui tidak selamat

Kita boleh menggunakan Penunjuk dalam pakej tidak selamat untuk menukar antara tatasusunan bait dan struct. Kod sampel adalah seperti berikut:

package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{Name: "Tom", Age: 18}

    size := int(unsafe.Sizeof(p))
    fmt.Printf("struct size: %d
", size)

    b := make([]byte, size)
    pptr := unsafe.Pointer(&p)

    for i := 0; i < size; i++ {
        b[i] = *(*byte)(unsafe.Pointer(uintptr(pptr) + uintptr(i)))
    }

    fmt.Printf("byte array: %v
", b)

    q := (*Person)(unsafe.Pointer(&b[0]))
    fmt.Printf("person: %v
", q)
}

Dalam kod di atas, kami mencipta struktur Orang, menukarnya kepada tatasusunan bait dan menukarnya semula kepada struktur Orang melalui penuding. Kami menggunakan Penunjuk dan uintptr daripada pakej yang tidak selamat untuk menukar antara penunjuk dan integer.

Selepas menjalankan kod ini, hasil output adalah seperti berikut:

struct size: 16
byte array: [84 111 109 0 0 0 0 0 0 0 0 0 18 0 0 0]
person: &{Tom 18}

Walaupun kaedah ini boleh mencapai penukaran, ia mempunyai risiko keselamatan tertentu dan perlu digunakan dengan berhati-hati.

2. Penukaran melalui reflect

Pakej Reflect ialah pakej yang sangat berkuasa di Golang Anda boleh menggunakannya untuk melakukan inferens jenis pada pembolehubah dan fungsi panggilan. Apabila menukar antara tatasusunan bait dan struct, kita boleh menggunakan Nilai dan Jenis daripada pakej mencerminkan. Kod sampel adalah seperti berikut:

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    Name string
    Age  int
}

func main() {
    p := Person{Name: "Tom", Age: 18}

    size := int(reflect.TypeOf(p).Size())
    fmt.Printf("struct size: %d
", size)

    b := make([]byte, size)
    reflect.ValueOf(&p).Elem().Interface()
    for i := 0; i < size; i++ {
        b[i] = *(*byte)(unsafe.Pointer(uintptr(reflect.ValueOf(&p).Elem().UnsafeAddr()) + uintptr(i)))
    }

    fmt.Printf("byte array: %v
", b)

    var q Person
    s := reflect.ValueOf(&q).Elem()
    for i := 0; i < size; i++ {
        s.Field(i).SetInt(int64(b[i]))
    }

    fmt.Printf("person: %v
", q)
}

Kami menggunakan Jenis dan Nilai dalam pakej mencerminkan untuk mendapatkan saiz dan nilai struktur, dan mendapatkan struktur dalam ingatan melalui reflect.ValueOf(&p).Elem() Penunjuk .UnsafeAddr(), kemudian gunakan uintptr dan unsafe.Pointer untuk penukaran jenis, dan akhirnya melintasi tatasusunan bait untuk tugasan, kemudian tatasusunan bait boleh ditukar menjadi struct.

Selepas menjalankan kod ini, output adalah seperti berikut:

struct size: 16
byte array: [84 111 109 0 0 0 0 0 0 0 0 0 18 0 0 0]
person: {Tom 84}

Disebabkan perbezaan dalam susunan storan antara tatasusunan bait dan struct, kami perlu mengendalikan susunan tatasusunan bait secara manual untuk betul menukar kepada struct.

Ringkasan

Terdapat dua cara untuk menukar tatasusunan bait dan struct dalam Golang: satu ialah menukar antara penuding, integer dan tatasusunan bait melalui pakej yang tidak selamat; alamat dilakukan melalui pakej mencerminkan. Kedua-dua kaedah mempunyai kelebihan dan kekurangan mereka sendiri, dan anda perlu memilih mengikut situasi tertentu apabila menggunakannya. Pada masa yang sama, apabila menukar tatasusunan dan struktur bait, anda perlu memberi perhatian kepada butiran seperti susunan tatasusunan bait dan jenis medan dalam struct.

Atas ialah kandungan terperinci golang byte转struct. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:golang tetapkan laluan projekArtikel seterusnya:golang tetapkan laluan projek