2013-04-06 18 views
2
package main 

import (
     "bytes" 
     "encoding/binary" 
     "fmt" 
) 

func main() { 
     aa := uint(0xFFFFFFFF) 
     fmt.Println(aa) 
     byteNewbuf := []byte{0xFF, 0xFF, 0xFF, 0xFF} 
     buf := bytes.NewBuffer(byteNewbuf) 
     tt, _ := binary.ReadUvarint(buf) 
     fmt.Println(tt) 
} 

需要將4字節數組轉換爲uint32,但爲什麼結果不相同? 去其它版本:1.1的β將字節片段的數據解碼爲Uint32

+0

可能的重複[如何轉換\ [4 \] uint8到uint32在Go?](http://stackoverflow.com/questions/7380158/how-to-convert-4uint8-into-uint32-in-go ) – peterSO 2013-04-06 12:42:46

回答

4
tt := uint32(buf[0])<<24 | uint32(buf[1])<<16 | uint32(buf[2]) <<8 | 
     uint32(buf[3]) 

爲BE或

tt := uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2]) <<16 | 
     uint32(buf[3]) <<24 

爲LE。 varint是一種不同類型的編碼(32位數字可以有多達5個字節的編碼形式,64位數字最多10)。varint是一種不同類型的編碼。

  • 無需爲[]字節創建緩衝區。改爲直接在字節片上使用Varint或Uvarint。

  • 你扔掉了函數返回的錯誤。第二個結果表明有多少個字節被讀取或者是否有問題。有一個問題,同時解碼0xff,0xff,0xff,0xff作爲uvarint。

1

這裏是如何使用encoding/binary包來做你想做的。請注意,您不希望使用var函數中的任何函數作爲可變長度編碼的函數。

Playground version

package main 

import (
    "bytes" 
    "encoding/binary" 
    "fmt" 
    "log" 
) 

func main() { 
    aa := uint(0xFFFFFF0F) 
    fmt.Println(aa) 
    tt := uint32(0) 

    byteNewbuf := []byte{0x0F, 0xFF, 0xFF, 0xFF} 
    buf := bytes.NewBuffer(byteNewbuf) 
    err := binary.Read(buf, binary.LittleEndian, &tt) 
    if err != nil { 
     log.Fatalf("Decode failed: %s", err) 
    } 
    fmt.Println(tt) 
} 

結果是

4294967055 
4294967055 
+0

與「直接」解決方案相比:1)更多的線2)慢得多3)產生完全不必要的垃圾以便收集。重點是什麼? – zzzz 2013-04-06 10:23:20

+1

重點是顯示OP如何正確使用編碼/二進制!對於一個'uint32',我同意你的看法,但是複雜的數據結構,浮點值等的編碼/二進制獲勝。 – 2013-04-06 10:50:39

+2

我在OP中看不到複雜的數據結構,浮點值等。我看到_「需要將4個字節的數組轉換爲uint32」_。通過使用'interface {}'並使用反射(sic!)的'bytes.Buffer'和'binary.Read'來做到這一點是不可思議的。 (-1) – zzzz 2013-04-06 12:25:33

-1

Numeric types

byte  alias for uint8 

由於byte是別名uint8,你的問題, 「需要轉換4個字節數組UINT32」,已經有了答案:

How to convert [4]uint8 into uint32 in Go?

Package binary

[Uvarints和] Varints是編碼整數的方法使用一個 或更多字節;具有較小絕對值的數字採用較小的 字節數。有關規範,請參閱 http://code.google.com/apis/protocolbuffers/docs/encoding.html

由於Uvarint s爲整數表示和存儲的一個特殊形式的,你應該只使用已寫入與Uvarint函數值的ReadUvarint功能。

例如,

package main 

import (
    "bytes" 
    "encoding/binary" 
    "fmt" 
) 

func main() { 
    buf := make([]byte, 10) 
    x := uint64(0xFFFFFFFF) 
    fmt.Printf("%2d %2d %v\n", x, len(buf), buf) 
    n := binary.PutUvarint(buf, x) 
    buf = buf[:n] 
    fmt.Printf("%2d %2d %v\n", x, len(buf), buf) 
    y, err := binary.ReadUvarint(bytes.NewBuffer(buf)) 
    if err != nil { 
     fmt.Println(err) 
     return 
    } 
    fmt.Printf("%2d %2d %v\n", y, len(buf), buf) 
} 

輸出:

4294967295 10 [0 0 0 0 0 0 0 0 0 0] 
4294967295 5 [255 255 255 255 15] 
4294967295 5 [255 255 255 255 15] 
+1

不,他不應該使用ReadUvarint從字節片段中讀取uvarint - 就像在你的例子中,通過''io.Readder''中的'io.Readder'完全不必要地增加了間接(和垃圾產生) bytes.Buffer'。爲了從字節片段讀取[u] varint(s),有[Varint](http://golang.org/pkg/encoding/binary/#Varint)和[Uvarint](http://golang.org/pkg/) encoding/binary /#Uvarint),它直接處理字節片段。 (-1) – zzzz 2013-04-06 19:06:41

5

您可以從encoding/binaryByteOrder對象之一做到這一點。例如:

package main 

import (
     "encoding/binary" 
     "fmt" 
) 

func main() { 
     aa := uint(0x7FFFFFFF) 
     fmt.Println(aa) 
     slice := []byte{0xFF, 0xFF, 0xFF, 0x7F} 
     tt := binary.LittleEndian.Uint32(slice) 
     fmt.Println(tt) 
} 

如果你的數據是大端格式,你可以改用上binary.BigEndian同樣的方法。