星号(* struct)表示法在golang中是什么意思
// NewReaderSize returns a new Reader whose buffer has at least the specified
43 // size. If the argument io.Reader is already a Reader with large enough
44 // size, it returns the underlying Reader.
45 func NewReaderSize(rd io.Reader, size int) *Reader {
46 // Is it already a Reader?
47 b, ok := rd.(*Reader)
48 if ok && len(b.buf) >= size {
49 return b
50 }
51 if size < minReadBufferSize {
52 size = minReadBufferSize
53 }
54 r := new(Reader)
55 r.reset(make([]byte, size), rd)
56 return r
57 }
When I use os.Open to open a file
dictFile, err := os.Open(file)
I'm going to pass dicFile to
reader := bufio.NewReader(dictFile)
I found the underlying code is using func NewReaderSize
, but what I can not understand is rd.(*Reader)
. Reader
is the struct type contained in package bufio
. Asterisk followed by a struct is from what I see to get the value from pointer Reader
, but it is not a pointer, so it does not make sense. Further more, it's using dot operator rd.(*Reader)
, I totally got confused. What's the meaning of this kind of usage in line 47? What kind of notation it is?
newReaderSize
takes a reader (io.Reader
interface) and returns a pointer to Reader
(struct
defined in bufio
).
This is called a type assertion:
b, ok := rd.(*Reader)
From golang spec:
For an expression x of interface type and a type T, the primary expression x.(T) asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion.
This line is taking that reader and asserting it is a type of *Reader
, if it succeeds and that Reader
has buffer big enough its immedietly returned (because it's already what we want).
The syntax in line 47 in your example is a Type Assertion, it asserts the value of interface variables to be of a specific type. Concretely in your case, the statement
b, ok := rd.(*Reader)
asserts the underlying value of the interface rd
to be of type *Reader
(a pointer to a value of struct Reader
), giving you b
of type *Reader
and a boolean value ok
that indicates whether the assertion is OK and the underlying value really is of type *Reader
.
An abstract example (play):
type readerA struct {}
func Read(a []byte) (int, error) {}
type readerB struct {}
func Read(a []byte) (int, error) {}
func TakesAReader(r io.Reader) {
val, ok := r.(*readerA)
fmt.Println(val, ok)
}
TakesAReader(&readerA{}) // prints &{}, true
TakesAReader(&readerB{}) // prints nil, false
So you see, type assertions are just a way to pull out the value that is covered by an interface.