@blajlhimik

Как организовать код в интерфейсы golang?

У меня есть разные модели оборудования которые делают то же самое но по своему, я хочу организовать так код чтобы при добавления обработчика нового оборудования я делал только пакет с функциями описанных в какой то главный интерфейс и где то добавил ее в перечисление. Но только чтобы в остальных местах вызов методов выглядил одинаково.

Вот как то так :
60e6e9a3047a6018017034.png

test123.go:
package test123

type Command interface {
	Open()
	Close()
}


a123.go:
package a123

import "fmt"

type A123struct struct {
	hash     string
	iftrue   bool
	password string
}

func (variab *A123struct) Open() {
	fmt.Println("open a123", variab.hash, variab.iftrue, variab.password)
}

func (variab *A123struct) Close() {
	fmt.Println("close a123", variab.hash, variab.iftrue, variab.password)
}


b123.go:
package b123

import "fmt"

type B123struct struct {
	id   string
	date bool
}

func (variab *B123struct) Open() {
	fmt.Println("open b123", variab.id, variab.date)
}

func (variab *B123struct) Close() {
	fmt.Println("close b123", variab.id, variab.date)
}


добавление обработчика это добавление нового пакета (c123 например). Как связать интерфейс с пакетами. Какую конструкцию создать чтобы вызов методов сам определил какую надо вызвать. Это просто так задумал может это делается совсем по другому
  • Вопрос задан
  • 166 просмотров
Решения вопроса 1
EvgenyMamonov
@EvgenyMamonov Куратор тега Go
Senior software developer, system architect
Интерфейс нужно будет указывать как параметр функций, которые будут уметь работать с вашим интрейфейсом.
Например.
func Process(device test123.Command) {
    device.Open()
    device.Close()
}

dev1 := a123.A123struct{параметры...}
Process(dev1)

dev2 := b123.B123struct{параметры...}
Process(dev2)

// или с перечислением
devices := []test123.Command{dev1, dev2}
for _, device := range devices {
    Process(device)
}


Приведу пример более похожий на реальный.
Допустим нам нужно сделать логгер, который умеет писать в файл (если указан в настройках), а если не указан - тогда в консоль.
Пример намеренно упрощён, чтобы было проще уловить суть.
package main

import (
    "fmt"
    "os"
)

// Logger интерфейс логгера.
type Logger interface {
    Error(msg string)
}

// StdoutLogger реализация интерфейса Logger для вывода сообщений в консоль.
type StdoutLogger struct{}

// NewStdoutLogger конструктор (возвращаем структуру, не интерфейс)
func NewStdoutLogger() *StdoutLogger {
    return &StdoutLogger{}
}

// Error добавляет в лог сообщение с уровнем error
func (l *StdoutLogger) Error(msg string) {
    fmt.Printf("ERROR: %s\n", msg)
}

// FileLogger реализация интерфейса Logger для вывода сообщений в файл.
type FileLogger struct {
    FileName string
    Fh       *os.File
}

// NewFileLogger конструктор.
func NewFileLogger(fileName string) *FileLogger {
    logger := &FileLogger{
        FileName: fileName,
    }
    fh, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0664)
    if err != nil {
        panic(fmt.Sprintf("FileLogger: can't open log file: %s: %s\n", fileName, err))
    }
    logger.Fh = fh

    return logger
}

// Error добавляет в лог сообщение с уровнем error.
func (l *FileLogger) Error(msg string) {
    l.Fh.WriteString(fmt.Sprintf("ERROR: %s\n", msg))
}

// ProcessData какая то функция, которая использует логгер и которую не должна беспокоить реализация логгера.
// Тут тип параметра должен быть интерфейс.
func ProcessData(logger Logger) {
    logger.Error("Data process some error happened")
}

func main() {
    var logger Logger

    // если лог файл не указан - используем StdoutLogger, если указан - используем FileLogger
    logFile := os.Getenv("LOG_FILE")
    if logFile != `` {
        logger = NewFileLogger(logFile)
    } else {
        logger = NewStdoutLogger()
    }

    ProcessData(logger)
}

После запуска go run main.go вы увидите сообщение в консоли:
ERROR: Data process some error happened
а если запустите вот так LOG_FILE=test.log go run main.go
или
export LOG_FILE=test.log
go run main.go

То будет создан файл test.log и туда будет добавлено тоже сообщение, что вы видели в консоли.

Если понятнее не стало - пишите, будут рад помочь.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы