7

Golang 介面教學與範例

 3 years ago
source link: https://calvertyang.github.io/2019/11/19/golang-interfaces-tutorial-with-examples/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

原文:CalliCoderGolang Interfaces Tutorial with Examples

Go 的介面

Go 中的介面是使用一組方法簽名定義的型別。介面定義了類似物件型別的行為。

舉例來說,這是一個定義幾何形狀行為的介面:

// Go Interface - `Shape`
type Shape interface {
	Area() float64
	Perimeter() float64
}

使用 type 關鍵字定義介面,後面接著介面名稱和關鍵字 interface。然後,在大括號內指定一組方法簽名。

在 Go 中實作介面

要實作介面,你只需要實作介面中宣告的所有方法。

Go 的介面是隱含實作的

與 Java 等其他語言不同,你不需要使用如 implements 關鍵字之類的方法來明確指定一種型別來實作介面。

以下是兩種實作 Shape 介面的 struct 型別:

// Struct type `Rectangle` - implements the `Shape` interface by implementing all its methods.
type Rectangle struct {
	Length, Width float64
}

func (r Rectangle) Area() float64 {
	return r.Length * r.Width
}

func (r Rectangle) Perimeter() float64 {
	return 2 * (r.Length + r.Width)
}
// Struct type `Circle` - implements the `Shape` interface by implementing all its methods.
type Circle struct {
	Radius float64
}

func (c Circle) Area() float64 {
	return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
	return 2 * math.Pi * c.Radius
}

func (c Circle) Diameter() float64 {
	return 2 * c.Radius
}

使用具有明確數值的介面型別

除非我們將其與實作所有方法的具體型別一起使用,否則介面本身並不是那麼有用。

讓我們來看看如何將介面與明確數值一起使用。

  • 介面型別可以包含實作其所有方法的任何值

    package main
    
    import (
    	"fmt"
    	"math"
    )
    
    func main() {
    	var s Shape = Circle{5.0}
    	fmt.Printf("Shape Type = %T, Shape Value = %v\n", s, s)
    	fmt.Printf("Area = %f, Perimeter = %f\n\n", s.Area(), s.Perimeter())
    
    	var s1 Shape = Rectangle{4.0, 6.0}
    	fmt.Printf("Shape Type = %T, Shape Value = %v\n", s1, s1)
    	fmt.Printf("Area = %f, Perimeter = %f\n", s1.Area(), s1.Perimeter())
    }
    # Output
    Shape Type = main.Circle, Shape Value = {5}
    Area = 78.539816, Perimeter = 31.415927
    
    Shape Type = main.Rectangle, Shape Value = {4 6}
    Area = 24.000000, Perimeter = 20.000000
  • 使用介面型別作為函數的參數

    package main
    
    import "fmt"
    
    // Generic function to calculate the total area of multiple shapes of different types
    func CalculateTotalArea(shapes ...Shape) float64 {
    	totalArea := 0.0
    	for _, s := range shapes {
    		totalArea += s.Area()
    	}
    	return totalArea
    }
    
    func main() {
    	totalArea := CalculateTotalArea(Circle{2}, Rectangle{4, 5}, Circle{10})
    	fmt.Println("Total area = ", totalArea)
    }
    # Output
    Total area =  346.7256359733385
  • 將介面型別用於欄位

    package main
    
    import "fmt"
    
    // Interface types can also be used as fields
    type MyDrawing struct {
    	shapes  []Shape
    	bgColor string
    	fgColor string
    }
    
    func (drawing MyDrawing) Area() float64 {
    	totalArea := 0.0
    	for _, s := range drawing.shapes {
    		totalArea += s.Area()
    	}
    	return totalArea
    }
    
    func main() {
    	drawing := MyDrawing{
    		shapes: []Shape{
    			Circle{2},
    			Rectangle{3, 5},
    			Rectangle{4, 7},
    		},
    		bgColor: "red",
    		fgColor: "white",
    	}
    
    	fmt.Println("Drawing", drawing)
    	fmt.Println("Drawing Area = ", drawing.Area())
    }
    # Output
    Drawing {[{2} {3 5} {4 7}] red white}
    Drawing Area = 55.56637061435917

介面數值:介面型別如何與明確數值一起使用?

在底層,介面值可以認為是一個由值和具體型別組成的元組:

// interface
(value, type)

讓我們來看一個範例了解更多資訊:

package main

import "fmt"

func main() {
	var s Shape

	s = Circle{5}
	fmt.Printf("(%v, %T)\n", s, s)
	fmt.Printf("Shape area = %v\n", s.Area())

	s = Rectangle{4, 7}
	fmt.Printf("(%v, %T)\n", s, s)
	fmt.Printf("Shape area = %v\n", s.Area())
}
# Output
({5}, main.Circle)
Shape area = 78.53981633974483
({4 7}, main.Rectangle)
Shape area = 28

查看以上程式的輸出,並注意變數 s 如何取得有關數值以及分配給它的 Shape 的型別的資訊。

當我們在介面上呼叫方法時,將執行其底層型別上同名的方法。

來說,在上面的程式中,當我們在變數 s 上呼叫 Area() 方法時,它將執行其底層型別 Area() 方法。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK