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 | ||
|  | } | ||
|  | ``` |