Recently I’ve been asked a question which is, what’s the difference between Golang and Java about interface?
I know there are some ‘syntactic sugar level’ differences, what I am interested is anything beneath the ground, like how does Golang and Java implement interface? What’s the most difference? Which one is more efficient? Why?
Could anyone post blogs link or source code about this topic? Source code is better.
Advertisement
Answer
Go Data Structures: Interfaces by Russ Cox
Go’s interfaces—static, checked at compile time, dynamic when asked for
Go’s interfaces let you use duck typing like you would in a purely dynamic language like Python but still have the compiler catch obvious mistakes like passing an int where an object with a Read method was expected, or like calling the Read method with the wrong number of arguments.
Interfaces aren’t restricted to static checking, though. You can check dynamically whether a particular interface value has an additional method.Interface Values
Languages with methods typically fall into one of two camps: prepare tables for all the method calls statically (as in C++ and Java), or do a method lookup at each call (as in Smalltalk and its many imitators, JavaScript and Python included) and add fancy caching to make that call efficient. Go sits halfway between the two: it has method tables but computes them at run time. I don’t know whether Go is the first language to use this technique, but it’s certainly not a common one.
Interface values are represented as a two-word pair giving a pointer to information about the type stored in the interface and a pointer to the associated data. Assigning b to an interface value of type Stringer sets both words of the interface value.The first word in the interface value points at what I call an interface table or itable (pronounced i-table; in the runtime sources). The itable begins with some metadata about the types involved and then becomes a list of function pointers. Note that the itable corresponds to the interface type, not the dynamic type.
The second word in the interface value points at the actual data, in this case a copy of b.Go’s dynamic type conversions mean that it isn’t reasonable for the compiler or linker to precompute all possible itables: there are too many (interface type, concrete type) pairs, and most won’t be needed. Instead, the compiler generates a type description structure for each concrete type like Binary or int or func(map[int]string). Among other metadata, the type description structure contains a list of the methods implemented by that type. Similarly, the compiler generates a (different) type description structure for each interface type like Stringer; it too contains a method list. The interface runtime computes the itable by looking for each method listed in the interface type’s method table in the concrete type’s method table. The runtime caches the itable after generating it, so that this correspondence need only be computed once.
Method Lookup Performance
Smalltalk and the many dynamic systems that have followed it perform a method lookup every time a method gets called. For speed, many implementations use a simple one-entry cache at each call site, often in the instruction stream itself. In a multithreaded program, these caches must be managed carefully, since multiple threads could be at the same call site simultaneously. Even once the races have been avoided, the caches would end up being a source of memory contention.Because Go has the hint of static typing to go along with the dynamic method lookups, it can move the lookups back from the call sites to the point when the value is stored in the interface.
How does Go interface dispatch work?
Method dispatch on an interface variable is the same as a vtable dispatch.
The first time a concrete type hits an interface type, it builds a hash table entry that points to a vtable. Second and subsequent assignments of the same type will do a much cheaper hash lookup to find the vtable. But the method dispatch itself is always equivalent to a vtable lookup.
Spec: Interface types
For more details see: Go: What’s the meaning of interface{}?
Here, two interesting use cases of interfaces in Go: Why are interfaces needed in Golang?
The error type is an interface type: How to compare Golang error objects
Calculate Area of 4 different shapes: Circle, Square, Rectangle and Triangle:
Explain Type Assertions in Go
Here in Go you don’t need do any thing special like Java keyword implements
for implementing an interface, in Go it is enough that your type just has that method with right signature.
Here is the code (try it on The Go Playground):
package main import "fmt" type Work struct { Name string } func (t Work) String() string { return "Stringer called." } func main() { w := Work{"Hi"} fmt.Println(w) }
output:
Stringer called.
Spec: type Stringer, and see the source:
type Stringer interface { String() string }
Stringer is implemented by any value that has a String method, which defines the “native” format for that value. The String method is used to print values passed as an operand to any format that accepts a string or to an unformatted printer such as Print.
Also see:
Why can’t I assign a *Struct to an *Interface?
Meaning of a struct with embedded anonymous interface?
Embedded Interface
Golang: what’s the point of interfaces when you have multiple inheritence