io.Reader インタフェースの

func Read(p []byte) (n int, err error)

で、全てを読みつくしたかどうかを判定する方法で迷っています。
思いつく限りでは以下の3つなのですが、優劣はありますでしょうか。

1.戻り値 n がゼロだったら「終わり」

package main

import (
    "bytes"
    "fmt"
)

func main() {

    r := bytes.NewBuffer([]byte{1, 2, 3})
    b := make([]byte, 2)

    for {
        n, err := r.Read(b)

        if n == 0 {
            break
        }

        if err != nil {
            panic(err)
        }

        fmt.Println(b[:n])
    }
}

B.戻り値 errio.EOF だったら「終わり」

    for {
        n, err := r.Read(b)

        if err != nil {
            if err == io.EOF {
                break
            }
            panic(err)
        }

        fmt.Println(b[:n])
    }

C.戻り値 n が 用意したバッファサイズより小さかったら「終わり」

    for {
        n, err := r.Read(b)

        if err != nil {
            panic(err)
        }

        fmt.Println(b[:n])

        if n < len(b) {
            break
        }
    }