The question may seem silly. I am recently learning golang. Naturally read articles, but did not understand. What exactly can I do with interfaces and can not do without them (or at great expense)? I just didn’t use them in the code and want to figure out when to use them.

    2 answers 2

    Interfaces in Go are a way to implement polymorphism .

    I will give a standard example with figures:

    package main import ( "math" "fmt" ) // Круг. type Circle struct { x, y, r float64 } // Прямоугольник. type Rectangle struct { x1, y1, x2, y2 float64 } // Интерфейс фигуры, которому удовлетворяют все типы, имеющие соответствующий // метод вычисления площади Area(). type Figure interface { Area() float64 } // Реализация интерфейса Figure для Circle. func (c *Circle) Area() float64 { return math.Pi * cr * cr } // Реализация интерфейса Figure для Rectangular. func (r *Rectangle) Area() float64 { return math.Abs(r.x2 - r.x1) * math.Abs(r.y2 - r.y1) } func main() { figures := make([]Figure, 0) // Срез фигур. // Мы можем добавлять в этот срез все, что удовлетворяет интерфейсу // Figure, несмотря на то, что это элементы разных типов: figures = append(figures, &Circle{0, 0, 10}) figures = append(figures, &Rectangle{0, 0, 10, 20}) // И теперь мы можем единообразно обрабатывать эти данные разных типов. for _, figure := range figures { fmt.Printf("Area of %#v = %f\n", figure, figure.Area()) } } 

    Result:

     $ go run figures.go Area of &main.Circle{x:0, y:0, r:10} = 314.159265 Area of &main.Rectangle{x1:0, y1:0, x2:10, y2:20} = 200.000000 

      The golang interfaces are quite a funny thing when viewed from the point of view of OOP languages. By and large, the golang interface is a set of methods without implementation. If you implement these methods for any strategy, this strategy can be used as an interface type, sometimes it is quite convenient. For example, there is a function that should collect information about different types and save them to the database, I need to use a framework that collects all the query for the transaction:

       func AddAllEntities(entityName string, entities []entity, defaults map[string]interface{}) { getHookScriptRes("AddPartOfSale", "salePartName", entities) for _, entity := range entities { q.NewAppend("save"+salePartName, entity.GetSaveParams(defaults)...) break } } 

      Also, I have several different entityOne, entityTwo, entityThree and I want to use them as an argument to the function that collects the transaction. To do this, I created an interface with a method that pulls out the fields I need from the attacks and in the map connects them to the columns in the table:

       type saveEntity interface { GetSaveParams(defaults map[string]interface{}) map[string]interface{} } 

      And for each of the strategies I write the implementation of this method:

       func (e1 *entityOne) GetSaveParams(defaults map[string]interface{}) []interface{} { tmpMap := map[string]interface{}{ "one": defaults["one"], "two": defaults["two"], "id": e1.Id, } return tmpMap } func (e2 *entityTwo) GetSaveParams(defaults map[string]interface{}) []interface{} { tmpMap := map[string]interface{}{ "one": defaults["one"], "two": defaults["two"], "name": e2.Name, } return tmpMap } func (e3 *entityThree) GetSaveParams(defaults map[string]interface{}) []interface{} { tmpMap := map[string]interface{}{ "one": defaults["one"], "two": defaults["two"], "name": e3.Price, } return tmpMap } 

      Now all my campaigns are also my interface type: saveEntity One of the most obvious uses of interfaces.