iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
Software Development

那些年,我們一起走過的Go錯系列 第 2

Day02-到底是誰的interface

  • 分享至 

  • xImage
  •  

前言


我記得我剛開始寫Go的時候
是先跟著前輩一起寫
不過這也是他第一次寫Go project

有天他就跟我說

他把Go project寫成了Java的形狀了
/images/emoticon/emoticon13.gif
那時候的我一臉茫然,想說他在說什麼???

本文


如果你是從Python跳過來寫GO,應該不會有這種問題

因為你本來就是隻太極鴨,無招勝有招(大誤)(註1)

但如果你是從C#或Java的世界重生到Go的世界

有可能

因為在Go Playground待的不夠久

出新手村就踩到這個大雷

  • 先讓我們看看Java如何使用interface
// 介面定義在 Notifier.java 檔案中
public interface Notifier {
    void send(String message);
}
// 實作類別定義在 EmailNotifier.java 檔案中
public class EmailNotifier implements Notifier {
    @Override
    public void send(String message) {
        System.out.println("Sending email: " + message);
    }
}
// 使用者
public class Main {
    public static void main(String[] args) {
        Notifier notifier = new EmailNotifier();
        notifier.send("Hello, World!");
    }
}
  • Golang使用interface的範例
// 包名為 email
package email

import "fmt"

// EmailNotifier 
type EmailNotifier struct {
   
}

// 實作 Send 方法
func (e *EmailNotifier) Send(message string) error {
    fmt.Println("Sending email:", message)
    return nil
}
package main

import (
    "myapp/email"
)

// 在使用者端定義 Notifier 介面
type Notifier interface {
    Send(message string) error
}

func Notify(n Notifier, message string) error {
    return n.Send(message)
}

func main() {
    emailNotifier := &email.EmailNotifier{}
    Notify(emailNotifier, "Hello, World!")
}

你發現了嗎?

  • 在Golang的世界,使用者在自己世界的中心定義了介面,呼叫了愛情 實作
    而且是給的是隱隱約約的愛 隱性實作
    (Python表示我懂藏在心裡的愛,因為我是隻鴨子) 註1:Duck Typing

  • 而在Java的世界,是工具人送上介面和實作大禮包,並且毫無保留地告訴你,
    我用了implements實實在在作了介面

其實這就是

傳說中的SOLID 原則
Interface Segregation Principle(介面隔離原則)
應該將 Interface 拆分成小而專一的部分,讓使用者只需要關注他們實際需要的功能。


結案陳詞

你應該讓使用者勇敢地說自己想要的介面
優點如下:

  1. 降低耦合度
  2. 提高可測試性 (使用github.com/golang/mock/mockgen 利用介面產生,測試煩惱減半)
  3. 實作與介面是隱式的,只要實作了介面中定義的方法,即可被視為實作了該介面。
  4. 易於察覺介面臃腫的問題~! 如果介面都在實作方,沒有這麼一目了然。原來這些傢伙不是一夥的(內聚性低)或者忘記刪掉不會再用的

但總有例外,就是開不了口讓你知道

在Go標準庫中
介面通常定義在標準庫的包內,例如 io.Reader、io.Writer、fmt.Stringer 、enconding等。

那為什麼介面定義在「遠離使用者」的位置 ??

  • 每一位使用者(developer)都各自照自己需求呼叫標準庫,請問標準庫錯了嗎? 阿扁錯了嗎?
    標準庫需要維穩,一個介面不能少!!! 統一的介面,大家才能一起用
  • 只有一個介面,沒有各自表述,大家才能省時間不需要自己重寫定義

註1:Python 沒有明確定義的interface
Duck Typing(鴨子類型)

class EmailNotifier:
    def send(self, message):
        print(f"Sending email: {message}")

class SMSNotifier:
    def send(self, message):
        print(f"Sending SMS: {message}")

def notify(notifier, message):
    notifier.send(message)

email_notifier = EmailNotifier()
sms_notifier = SMSNotifier()

notify(email_notifier, "Hello via Email!")
notify(sms_notifier, "Hello via SMS!")

Note:在Go的世界,其實你不寫interface在消費者端 ,程式還是能動,但就是不要被人知道


上一篇
Day01-系列文介紹、規劃
下一篇
DAY03-GO的簡單至上
系列文
那些年,我們一起走過的Go錯6
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言