// 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?
A struct (short for "structure") is a collection of data fields with declared data types. Golang has the ability to declare and create own data types by combining one or more types, including both built-in and user-defined types.
In Go a pointer is represented using the * (asterisk) character followed by the type of the stored value. In the zero function xPtr is a pointer to an int . * is also used to “dereference” pointer variables. Dereferencing a pointer gives us access to the value the pointer points to.
The * character is used to define a pointer in both C and Go. Instead of a real value the variable instead has an address to the location of a value. The & operator is used to take the address of an object.
A struct variable in Golang can be copied to another variable easily using the assignment statement(=). Any changes made to the second struct will not be reflected back to the first struct.
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.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With