iT邦幫忙

2023 iThome 鐵人賽

DAY 6
0
SideProject30

HOW TO GO系列 第 6

06. 介面 (Interface)

  • 分享至 

  • xImage
  •  

Interface

interface 在 Go 中兩種不同的意義,一種是作為抽象化使用,另一種作為型別使用。Go 沒有繼承這樣子功能,但是可以透過組合或者介面的方式,達到類似的需求。

介面

package main

import "fmt"

type Shape interface {
	Area() float64
}

type Rectangle struct {
	W float64
	H float64
}

func (r Rectangle) Area() float64 {
	return r.W * r.H
}

type Circle struct {
	R float64
}

func (c Circle) Area() float64 {
	return 3.14 * c.R * c.R
}

func main() {
	rect := Rectangle{W: 5, H: 3}
	circle := Circle{R: 2}

	// 使用接口
	shapes := []Shape{rect, circle}

	for _, shape := range shapes {
		fmt.Printf("Area: %.2f\n", shape.Area())
	}
}

空介面

package main

import (
	"fmt"
	"reflect"
)

func main() {
	foo(123)   // 123 int
	foo("str") // str string
}

// 可以接任意型別參數
func foo(a interface{}) {
	fmt.Println(a, reflect.TypeOf(a))
}

型別斷言 (type assertion)

package main

import (
	"fmt"
	"reflect"
)

func main() {
	foo(123)   // 123 int
	foo("str") // str string
}

// 可以接任意型別參數
func foo(a interface{}) {
	fmt.Println(a, reflect.TypeOf(a))

	// 如果想要轉換成指定型別時
	// str2 := a.(string) // 如果不檢查是否可以轉換,會引發 panic

	// 所以加上檢查
	str, ok := a.(string)
	if ok {
		fmt.Println("is string: " + str)
	}

	// 可以根據不同的型態做不同的行為,達成泛型的功能
	// 使用 switch
	switch v := a.(type) {
	case int:
		fmt.Println("int")
	case string:
		fmt.Println("string")
	case bool:
		fmt.Println("bool")
	case nil:
		fmt.Println("nil")
	default:
		fmt.Println("unknown", v)
	}
}

補充1. 泛型 (Generics)

Go 1.18 is released!,於 Go 1.18 釋出後開始支援泛型,因此可以使用此功能取代使用 nterface{} 當作任意參數的方式

Tutorial: Getting started with generics


上一篇
05. 函式&方法 (Function & Method)
下一篇
07. Goroutine & Channel (1)
系列文
HOW TO GO30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言