Bagaimana untuk mengawal nilai integer kepada hex menggunakan go-yaml?

PHPz
Lepaskan: 2024-02-09 09:33:09
ke hadapan
478 orang telah melayarinya

如何使用 go-yaml 将整数值编组为十六进制?

editor php Banana akan memperkenalkan anda cara menggunakan go-yaml untuk mengawal nilai integer ke dalam perenambelasan. go-yaml ialah perpustakaan bahasa Go untuk memproses data format YAML, yang menyediakan API yang ringkas dan mudah digunakan. Untuk menyusun nilai integer kepada perenambelasan, kita boleh menukar integer kepada hirisan bait dahulu dan kemudian gunakan fungsi fmt.Sprintf untuk memformat hirisan bait menjadi rentetan perenambelasan. Akhir sekali, kita boleh menggunakan perpustakaan go-yaml untuk menulis rentetan yang diformatkan ke dalam fail YAML. Kaedah ini mudah dan cekap serta boleh memenuhi keperluan kita. Seterusnya, mari kita lihat lebih dekat pada langkah pelaksanaan khusus.

Kandungan soalan

Saya mempunyai struktur dengan medan integer yang bermakna kepada manusia dalam perwakilan heksadesimal. Contohnya, tetapkan ini kepada medan ID Vendor.

Saya ingin menyimpan data ini ke fail YAML untuk pengeditan manual dan kemudian memuatkannya daripada fail. Setakat yang saya faham, tiada masalah dengan perwakilan heksadesimal nombor dalam YAML itu sendiri, tetapi go-yaml (我使用 v3 ) mengekodkan integer dalam bentuk perpuluhan, dan saya tidak menemui cara biasa untuk menyimpannya dalam bentuk perenambelasan.

Mari ambil kod berikut sebagai titik permulaan:

import (
    //...
    "gopkg.in/yaml.v3"
)

type DeviceInfo struct {
    VendorId uint32 `yaml:"vendorid"`
}

func main() {
    deviceInfo := DeviceInfo{VendorId: 0xdeadbeef}

    yml, err := yaml.Marshal(deviceInfo)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(string(yml))
}
Salin selepas log masuk

Kod ini menjana YAML dengan nilai perpuluhan:

vendorid: 3735928559
Salin selepas log masuk

Seterusnya, go-yaml 允许您为自己的类型创建自定义封送拆收器。我这样做了(我故意省略了 fmt.Sprintf() 格式字符串中的 0x awalan):

type Uint32Hex uint32

func (U Uint32Hex) MarshalYAML() (interface{}, error) {
    return fmt.Sprintf("%x", U), nil
}

type DeviceInfo struct {
    VendorId Uint32Hex `yaml:"vendorid"`
}

func main() {
    // the same code
}
Salin selepas log masuk

Kod ini menjana nilai perenambelasan tanpa awalan 0x (logik buat masa ini):

vendorid: deadbeef
Salin selepas log masuk

Tetapi jika saya menambah 0x awalan dalam marshaler tersuai:

func (U Uint32Hex) MarshalYAML() (interface{}, error) {
    return fmt.Sprintf("0x%x", U), nil
}
Salin selepas log masuk

Nilai dijana dengan betul, tetapi bukannya nombor, ia adalah rentetan:

vendorid: "0xdeadbeef"
Salin selepas log masuk

Untuk membongkar baris ini menjadi nombor, saya juga terpaksa menulis unmarshaler tersuai. Saya tidak suka penyelesaian ini.

Akhirnya saya mempunyai soalan berikut:

  1. Adakah terdapat cara mudah untuk menjana nombor perenambelasan menggunakan go-yaml yang saya tidak temui?

  2. Adakah mungkin untuk membuat pengekod tersuai berdasarkan go-yaml sebagai lanjutan pakej, tanpa mengubah pakej itu sendiri? Bagi saya, cara yang lebih mudah ialah dengan menghantar teg format dalam penerangan struktur, contohnya, seperti ini:

    type DeviceInfo struct {
        VendorId uint32 `yaml:"vendorid,hex"`
    }
    
    Salin selepas log masuk
  3. Jika ini memerlukan perubahan pada kod pakej, apakah pendekatan Go terhadap situasi ini? Hanya salin fail pakej ke dalam projek saya, ubah suai mengikut keperluan dan import secara tempatan?

Penyelesaian

Masalahnya di sini ialah memetik rentetan dalam yaml adalah pilihan, tetapi go-yaml 使用与 JSON 编码器相同的内部架构。这意味着首先处理自定义封送处理,然后完全独立地应用引用逻辑。 deadbeef 没有被引用,但 0xdeadbeef 被引用的原因是因为后者是一个数字。它被引用,这样当它知道它应该是一个字符串时,它就不会意外地被解组为数字,因为您的自定义封送拆收器返回了一个字符串。由于 deadbeef menggunakan skema dalaman yang sama seperti pengekod JSON. Ini bermakna bahawa marshaling tersuai dikendalikan terlebih dahulu dan kemudian logik petikan digunakan sepenuhnya secara bebas. deadbeef tidak dirujuk, tetapi sebab mengapa 0xdeadbeef dirujuk adalah kerana yang terakhir

ialah nombor
    . Ia dipetik supaya ia tidak secara tidak sengaja menyahmarshal menjadi nombor kerana marshaler tersuai anda mengembalikan rentetan apabila ia tahu ia sepatutnya menjadi rentetan. Memandangkan deadbeef tidak boleh dibaca sebagai nombor yang sah, petikan tidak diperlukan. Anda boleh melakukan dua perkara:
Pengambilan/pembuangan tersuai dilakukan dari rentetan:
  • func (U *Uint32Hex) UnmarshalYAML(value *yaml.Node) error {
        parsed, err := strconv.ParseUint(value.Value, 0, 32)
        *U = Uint32Hex(parsed)
        return err
    }
    
    Salin selepas log masuk
    go-yaml 并修改它。如果您这样做,则不应更改源文件中的导入。相反,您应该将 replace 指令添加到 go.mod
  • Fork dan ubah suainya. Jika anda melakukan ini, import dalam fail sumber tidak boleh diubah. Sebaliknya, anda harus menambah arahan ganti pada go.mod seperti ini:

    require gopkg.in/yaml.v3 v3.0.1
    
    replace gopkg.in/yaml.v3 v3.0.1 => ../yaml.v3 // Your local path to the fork
    
    Salin selepas log masuk
    🎜Saya lebih suka penyelesaian 1 kerana ia membolehkan anda menyusun nilai mengikut cara yang anda suka tanpa menyimpang daripada yaml yang dihasilkan oleh orang lain, dan tidak memerlukan anda mengekalkan cawangan. 🎜

    Atas ialah kandungan terperinci Bagaimana untuk mengawal nilai integer kepada hex menggunakan go-yaml?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

    sumber:stackoverflow.com
    Kenyataan Laman Web ini
    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
    Tutorial Popular
    Lagi>
    Muat turun terkini
    Lagi>
    kesan web
    Kod sumber laman web
    Bahan laman web
    Templat hujung hadapan
    Tentang kita Penafian Sitemap
    Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!