rand.Read() 和 io.ReadFull(rand.Reader) 的區別?


golang的隨機包 rand.go 中我們可以看到 rand.Read 其實是調用的io.Reader.Read()

   1: // Package rand implements a cryptographically secure
   2: // pseudorandom number generator.
   3: package rand
   4:  
   5: import "io"
   6:  
   7: // Reader is a global, shared instance of a cryptographically
   8: // strong pseudo-random generator.
   9: // On Unix-like systems, Reader reads from /dev/urandom.
  10: // On Windows systems, Reader uses the CryptGenRandom API.
  11: var Reader io.Reader
  12:  
  13: // Read is a helper function that calls Reader.Read.
  14: func Read(b []byte) (n int, err error) { return Reader.Read(b) }

io.Reader.Read() 函數的說明如下:

Read reads up to len(p) bytes into p. It returns the number of bytes read (0 <= n <= len(p)) and any error encountered. Even if Read returns n < len(p), it may use all of p as scratch space during the call. If some data is available but not len(p) bytes, Read conventionally returns what is available instead of waiting for more.

簡單來說,它讀出的數據,並不一定是指定長度的。

 

io.ReadFull 函數則相反:

ReadFull reads exactly len(buf) bytes from r into buf. It returns the number of bytes copied and an error if fewer bytes were read. The error is EOF only if no bytes were read. If an EOF happens after reading some but not all the bytes, ReadFull returns ErrUnexpectedEOF. On return, n == len(buf) if and only if err == nil.

讀取正好len(buf)長度的字節。如果字節數不是指定長度,則返回錯誤信息和正確的字節數。

當沒有字節能被讀時,返回EOF錯誤。

如果讀了一些,但是沒讀完產生EOF錯誤時,返回ErrUnexpectedEOF錯誤。

綜上對比,獲取隨機數時,最好是下面的寫法。

   1: import crand "crypto/rand"
   2:  
   3: r := make([]byte, length)
   4:  
   5: if _, err := io.ReadFull(crand.Reader, r); err != nil {
   6:     panic("error reading from random source: " + err.Error())
   7: }

 

參考資料:

rand.Read() or io.ReadFull(rand.Reader)?
https://groups.google.com/forum/#!topic/golang-nuts/eFS5GN-en3w


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM