Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does asterisk (*struct) notation mean in golang

Tags:

struct

go

// 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?

like image 385
user7031 Avatar asked Mar 27 '14 16:03

user7031


People also ask

What does * struct mean in Golang?

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.

What does * represent in Golang?

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.

What does the asterisk mean in Go?

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.

How do you assign one structure to another structure in Golang?

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.


2 Answers

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.

like image 119
nemo Avatar answered Oct 03 '22 16:10

nemo


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).

like image 42
Arjan Avatar answered Oct 03 '22 15:10

Arjan