16

When I read a copy of the docker/distribution source code, I find there are variables declared which make me quite confused. The code is:

var _ FileInfo = FileInfoInternal{}
var _ FileInfo = &FileInfoInternal{}

I don't know what the declare mean, and hope to get some help.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
JCheng
  • 179
  • 1
  • 6
  • Does this answer your question? [Ensure a type implements an interface at compile time in Go](https://stackoverflow.com/a/60663003) –  Mar 13 '20 at 03:33

2 Answers2

32

From the FAQ:

You can ask the compiler to check that the type T implements the interface I by attempting an assignment:

type T struct{} 
var _ I = T{}   // Verify that T implements I.

In this case the blank identifier _ stands for the variable name which is not needed here (and thus prevents a "declared but not used" error).

And more general from the spec:

The blank identifier provides a way to ignore right-hand side values in an assignment:

_ = x       // evaluate x but ignore it 
x, _ = f()  // evaluate f() but ignore second result value

By testing both FileInfoInternal{} and &FileInfoInternal{} you check if the interface is implemented with a value receiver. A value receiver will accept both a value and a pointer whereas the pointer receiver will only work with a pointer and the first assignment by value will fail.

The second test with &FileInfoInternal{} is not actually needed (as confirmed by the author in the comments) since the first test will pass with a value receiver and fail with a pointer received. Thus the second test is redundant.

This is an excellent article that explains the difference between value and pointer receivers and how they are used very well.

IamNaN
  • 6,654
  • 5
  • 31
  • 47
  • To avoid confusion I like to include a comment like `// Verify FileInfoInternal implements os.FileInfo` right above such variables. Personally I also stick those in `_test.go` files since I consider them a test like any other. – Dave C May 21 '15 at 16:21
  • 1
    Author here. Looking at this, I cannot recall why I put both declarations. The value assertion should be sufficient. We've been using these as annotations next to declarations for clarity in the following implementation. I've seen the convention of putting in the `_test.go` files and have accepted contributions in that manner. – stevvooe May 21 '15 at 20:12
1

FileInfo is an interface and the code checks whether FileInfoInternal implements this interface.

Salvador Dali
  • 214,103
  • 147
  • 703
  • 753