J'écris un tableau de nombres float32 au format octets sur un cluster Elasticache Redis à partir d'un script Python, puis je lis les octets (sous forme de chaîne) d'Elasticache dans un script Go. Comment reconvertir les octets sous forme de chaîne en tableau float32 d'origine dans le script Go ?
Exemple 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})
C'est un exemple que j'ai essayé dans Go (aire de jeux)
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] }
L'exemple de code que vous avez utilisé est "convertir l'hexadécimal, représenté sous forme de chaîne" ; vous avez les octets bruts (je pense basé sur aHex:CDCC8C3FCDCC0C4033335340
), donc une conversion directe est plus simple (bien que vous puissiez simplement octets en un chaîne hexadécimale puis effectuez la conversion, cela ajoute simplement du travail/de la complexité inutile).
De cette réponse nous obtenons (Playground) :
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 }
Commentaires de référence mis à jour :
Je suis encore un peu confus quant à ce que vous avez reçu, alors essayons les deux possibilités.
Si la requête Redis renvoie des données brutes (octets) sous forme de chaîne go (c'est-à-dire "xcdxccx8c?xcdxccx0c@33S@"
), alors vous pouvez Convertir "xcdxccx8c?xcdxccx0c@33S@"
),那么你可以将 转换为 []byte
en []byte
(Playground)
func main() { var aBytesStr string = "\xcd\xcc\x8c?\xcd\xcc\x0c@33S@" fmt.Println(GetFloatArray([]byte(aBytesStr))) }
Si Redis renvoie une chaîne contenant une représentation ASCII (/UTF-8) (c'est-à-dire CDCC
= []byte{0x41, 0x44, 0x43, 0x43}
), le moyen le plus simple est probablement de la décoder en utilisant encoding/hex (Playground)
func main() { aHex := "CDCC8C3FCDCC0C4033335340" b, err := hex.DecodeString(aHex) if err != nil { panic(err) } fmt.Println(GetFloatArray(b)) }
Notez que votre approche originale peut fonctionner, cependant, comme indiqué dans les commentaires ci-dessus, vous devez gérer Endianness donc ce qui suit fonctionnera (playground - vous pouvez être plus efficace, je suis ici pour plus de clarté) :
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)
Cependant, cela fait des hypothèses sur le processeur qui exécute le code, ce qui signifie que la réponse précédente est préférable.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!