93 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			93 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								title: Go Interfaces
							 | 
						||
| 
								 | 
							
								---
							 | 
						||
| 
								 | 
							
								# Go Interfaces
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								An interface in Go is a collection of methods. If a type can satisfy all methods in an interface then it is part of that interface.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Let's create a shape interface:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```go
							 | 
						||
| 
								 | 
							
								type shape interface {
							 | 
						||
| 
								 | 
							
								  area() float64
							 | 
						||
| 
								 | 
							
								  perimeter() float64
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This interface has two methods area() and perimeter(). Now lets create a rectangle that satisfies this interface:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```go
							 | 
						||
| 
								 | 
							
								type rectangle struct {
							 | 
						||
| 
								 | 
							
								  width, height float64
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (r rectangle) area() float64 {
							 | 
						||
| 
								 | 
							
								  return r.width * r.height
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (r rectangle) perimeter() float64 {
							 | 
						||
| 
								 | 
							
								  return 2*r.width + 2*r.height
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This rectangle contains all the methods needed to be a shape. Lets add another circle:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```go
							 | 
						||
| 
								 | 
							
								type circle struct {
							 | 
						||
| 
								 | 
							
								  radius float64
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (c circle) area() float64 {
							 | 
						||
| 
								 | 
							
								  return math.Pi * c.radius * c.radius  // math.Pi is the Pi constant in the go math package
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (c circle) perimeter() float64 {
							 | 
						||
| 
								 | 
							
								  return 2 * math.Pi * c.radius
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Now we can create a function that prints out the information of any shape:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```go
							 | 
						||
| 
								 | 
							
								func shapeInfo(s shape) {
							 | 
						||
| 
								 | 
							
									fmt.Println(reflect.TypeOf(s)) // reflect.TypeOf(s) will return the type of shape
							 | 
						||
| 
								 | 
							
									fmt.Println(s.area())
							 | 
						||
| 
								 | 
							
									fmt.Println(s.perimeter())
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Because both rectangle and circle satisfy the interface shape they can be used in the shapeInfo function:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```go
							 | 
						||
| 
								 | 
							
								func main() {
							 | 
						||
| 
								 | 
							
								r := rectangle{width:5, height:10}
							 | 
						||
| 
								 | 
							
								c := circle{radius: 12}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								shapeInfo(r)
							 | 
						||
| 
								 | 
							
								shapeInfo(c)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								Here we called shapeInfor for both a type rectangle and a type cricle.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If we removed the perimeter method from the circle type we would get an error such as:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								cannot use c (type circle) as type shape in argument to shapeInfo:
							 | 
						||
| 
								 | 
							
								        circle does not implement shape (missing perimeter method)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# The empty interface
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The empty interface is a common tool used by Go programmers. An empty interface contains no methods and has the form:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```go 
							 | 
						||
| 
								 | 
							
								interface{}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								An empty interface can hold values of any type as every type implements atleast zero methods. This can be useful for designing functions where the input type is unknown.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```go
							 | 
						||
| 
								 | 
							
								func describe(i interface{}) {
							 | 
						||
| 
								 | 
							
								  fmt.Printf("(%v, %T)\n", i, i) // Print the value and type of i
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 |