Saya sedang menulis tatasusunan nombor float32 dalam format bait ke gugusan Elasticache Redis daripada skrip Python, dan kemudian membaca bait (sebagai rentetan) daripada Elasticache dalam skrip Go. Bagaimana untuk menukar bait-sebagai-rentetan kembali kepada tatasusunan float32 asal dalam skrip Go?
Contoh Python:
import numpy as np import redis a = np.array([1.1, 2.2, 3.3], dtype=np.float32) a_bytes = a.tobytes(order="C") #I have also tried order="F" with no luck print(a_bytes) #Output: b'\xcd\xcc\x8c?\xcd\xcc\x0c@33S@' redis_client = redis.cluster.RedisCluster(host=<elasticache config endpoint>, port=6379) redis_client.mset_nonatomic({"key1": a_bytes})
Ini adalah contoh yang saya cuba di Go (taman permainan)
package main import ( "fmt" "math" "strconv" ) func main() { // aBytesStr is an example value retrieved from Elasticache // aBytesStr is type string, not raw bytes var aBytesStr string = "\xcd\xcc\x8c?\xcd\xcc\x0c@33S@" aHex := fmt.Sprintf("%X", aBytesStr) fmt.Println(aHex) // Output: CDCC8C3FCDCC0C4033335340 var aArr [3]float32 for i := 0; i < 3; i++ { aHex1 := aHex[i*8 : i*8+8] aParsed, err := strconv.ParseUint(aHex1, 16, 32) if err != nil { return } aArr[i] = math.Float32frombits(uint32(aParsed)) } fmt.Println(aArr) // Expected output: [1.1 2.2 3.3] // Actual output [-4.289679e+08 -4.2791936e+08 4.17524e-08] }
Contoh kod yang anda gunakan ialah "tukar hex, diwakili sebagai rentetan"; anda mempunyai bait mentah (saya rasa berdasarkan aHex:CDCC8C3FCDCC0C4033335340
) jadi penukaran langsung adalah lebih mudah (walaupun anda hanya boleh bait ke a rentetan hex dan kemudian lakukan penukaran, ia hanya menambah kerja/kerumitan yang tidak perlu).
Dari jawapan ini kami dapat (Taman Permainan):
func GetFloatArray(aBytes []byte) []float32 { aArr := make([]float32, 3) for i := 0; i < 3; i++ { aArr[i] = BytesFloat32(aBytes[i*4:]) } return aArr } func BytesFloat32(bytes []byte) float32 { bits := binary.LittleEndian.Uint32(bytes) float := math.Float32frombits(bits) return float }
Komen rujukan yang dikemas kini:
Saya masih keliru dengan apa yang anda terima, jadi mari kita cuba kedua-dua kemungkinan.
Jika pertanyaan redis mengembalikan data mentah (bait) sebagai rentetan pergi (iaitu "xcdxccx8c?xcdxccx0c@33S@"
), maka anda boleh Tukar "xcdxccx8c?xcdxccx0c@33S@"
),那么你可以将 转换为 []byte
kepada
func main() { var aBytesStr string = "\xcd\xcc\x8c?\xcd\xcc\x0c@33S@" fmt.Println(GetFloatArray([]byte(aBytesStr))) }
Jika Redis mengembalikan rentetan yang mengandungi perwakilan ASCII (/UTF-8) (iaitu CDCC
= []byte{0x41, 0x44, 0x43, 0x43}
), cara paling mudah mungkin ialah menyahkod ini menggunakan pengekodan/hex (Taman Permainan)
func main() { aHex := "CDCC8C3FCDCC0C4033335340" b, err := hex.DecodeString(aHex) if err != nil { panic(err) } fmt.Println(GetFloatArray(b)) }
Perhatikan bahawa pendekatan asal anda mungkin berkesan, namun, seperti yang dinyatakan dalam ulasan di atas, anda perlu menangani Endianness supaya perkara berikut akan berfungsi (taman permainan - anda boleh menjadi lebih cekap, saya di sini untuk kejelasan) :
byte1 := aHex[i*8 : i*8+2] byte2 := aHex[i*8+2 : i*8+4] byte3 := aHex[i*8+4 : i*8+6] byte4 := aHex[i*8+6 : i*8+8] aParsed, err := strconv.ParseUint(byte4+byte3+byte2+byte1, 16, 32)
Walau bagaimanapun, ini membuat andaian tentang CPU yang menjalankan kod, yang bermaksud jawapan sebelumnya adalah lebih baik.
Atas ialah kandungan terperinci Bagaimana untuk menukar bait kepada tatasusunan float32 dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!