B
B
blajlhimik2021-07-08 15:10:06
go
blajlhimik, 2021-07-08 15:10:06

How to organize code into golang interfaces?

I have different models of equipment that do the same but in their own way, I want to organize the code so that when adding a handler for new equipment, I only make a package with the functions described in some main interface and add it to the enumeration somewhere. But only so that in other places the method call looks the same.

Something like this:
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)
}


adding a handler is adding a new package (c123 for example). How to bind an interface to packages. What construction to create so that the method call itself determines which one should be called. It's just what I thought, maybe it's done differently

Answer the question

In order to leave comments, you need to log in

1 answer(s)
E
Evgeny Mamonov, 2021-07-08
@blajlhimik

The interface will need to be specified as a parameter of functions that will be able to work with your interface.
For example.

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)
}

I will give an example more similar to the real one.
Let's say we need to make a logger that can write to a file (if specified in the settings), and if not specified, then to the console.
The example has been deliberately simplified to make it easier to get the point across.
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)
}

After launch, go run main.goyou will see a message in the console:
ERROR: Data process some error happened
and if you run like this LOG_FILE=test.log go run main.go
or
export LOG_FILE=test.log
go run main.go

Then the test.log file will be created and the same message that you saw in the console will be added there.
If it does not become clearer - write, they will be happy to help.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question