Задача цикла импорта Голанга

У меня проблема с циклической зависимостью (цикл импорта не разрешен) в моем коде go, и я не уверен, как лучше всего ее решить. Я думаю, что мое непонимание интерфейсов golang может повлиять на мою способность видеть путь вперед.

Моя проблема - у меня два пакета:

  • Мероприятие - Событие в основном является «родительским» и будет вызывать много вызовов в пакет тренировок.
  • Тренировка - в одном случае мне нужно вызвать пакет событий, и это создает циклическую зависимость, потому что событие уже потребляет тренировку.

Как лучше всего разрешить Workout вызывать функцию (а не метод объекта) в домене событий?

Ниже мой упрощенный код, чтобы помочь предоставить некоторый контекст.

//workout package
//This is a private function on the workout package that is 
//attempting to call a public function on the Event Package
func findWorkoutAssociatedToActivityTcx(txcObject *DataTcx) *EventWorkout{
    return event.GetEventByDate(txcObject.ActivityDate, "", "")
}

Можно ли создать интерфейс для этой функции? Я не совсем понимаю, как бы я это сделал. Большое тебе спасибо.

// ОБНОВЛЕНИЯ - Код при попытке настроить интерфейс

//WorkoutPackage
//workout package
//This is a private function on the workout package that is
//attempting to call a public function on the Event Package
func findWorkoutAssociatedToActivityTcx(txcObject *DataTcx, userID, transactionID string) *Workout {
    //return event.GetEventByDate(txcObject.ActivityDate, "", "")
    MyEventFinder.GetEventByDate(txcObject.ActivityDate, userID, transactionID)
    return nil
}

var MyEventFinder EventFinder

type EventFinder interface {
    GetEventByDate(time.Time, string, string) (*sharedstructs.ListOfEvents, error)
}

// Пакет событий

type eventProvider struct{}

func (e eventProvider) GetEventByDate(date time.Time, userID, transactionID string) (*sharedstructs.ListOfEvents, error) {
        redFalconLogger.LogDebug("event.GetEventByDate: ", transactionID)
        if date.IsZero() || userID == "" {
            return nil, sharedstructs.InvalidData{Msg: "Invalid date or userID"}
        }
        //Create the query params
        queryParamArray, queryParamCreationError := createQueryParamForQueryByDate(&date, &userID)
        if queryParamCreationError != nil {
            return nil, queryParamCreationError
        }
        //perform the query - pass empty orderBy because I don't care
        queryResults, queryError := queryForEvent(*queryParamArray, "")
        if queryError != nil {
            switch queryError.(type) {
            case firestorehelper.UnqueryableCollection:
                return nil, sharedstructs.Forbidden{Msg: "operation is forbidden, probably due to malformed query"}
            default:
                return nil, sharedstructs.InternalServerError{Msg: "something went wrong in the query"}
            }
        }
        return queryResults, nil
    }

Возвращаемый тип - * EventWorkout. Разве вы не подумали бы об объединении этих пакетов, если они тесно связаны? В противном случае я бы создал другой пакет, чтобы определить интерфейсы, которые будут реализованы структурами из пакета event, и заменить им текущий тип возвращаемого значения.

Berkant Ipek 26.10.2018 07:17

@Berkant вам не нужен третий пакет для определения интерфейсов, потому что на интерфейс нужно ссылаться только у потребляющих пакетов, а не у пакетов, реализующих его; и, кроме того, идентичные интерфейсы могут быть определены в нескольких пакетах и ​​будут эквивалентными.

Adrian 26.10.2018 15:34
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
0
2
233
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы уверены, что можете сделать это с помощью интерфейса. В пакете событий необходимо передать GetEventByDate структуру получателя:

type eventProvider struct {}
func (e eventProvider) GetEventByDate(t time.Time, a, b string) *workout.EventWorkout{...}

Тогда в пакете тренировок:

type EventFinder interface {
    GetEventByDate(time.Time, string, string) *EventWorkout
}

Затем вы можете передать экземпляр eventProvider в пакет тренировки и использовать его только через интерфейс EventFinder, который не зависит от времени компиляции пакета event. Вы не показываете, как вы вызываете пакет workout, но это может быть либо параметром вызова метода, либо его установкой при создании структуры в пакете тренировки.

Большое спасибо! Это именно то, на что я надеялся. Думаю, я все еще немного не понимаю, как заполнить мой интерфейс в моем пакете тренировок. Должен ли я делать это в init () пакета событий? Будет ли это работать для тестирования? Я действительно пробовал что-то подобное и получил ошибку нулевой ссылки. Тем не менее, попробую то, что вы предлагаете. Спасибо

mornindew 26.10.2018 07:29

Как вы сейчас вызываете пакет тренировки? Я предположил, что все происходит из пакета событий, а затем перетекает в тренировку, если это так, просто создайте экземпляр eventProvider и передайте его, когда вы вызываете тренировку упаковка

Iain Duncan 26.10.2018 07:36

По большей части это правда, но и событие, и тренировка имеют отдельные API поверх них, так что кто-то может перейти непосредственно к тренировке (минуя событие). Я сохранил их как отдельные пакеты, потому что хочу иметь возможность легко разделять и обрабатывать их в микросервисах позже. Может быть, лучше всего использовать функцию init () события Event для заполнения интерфейса EventFinder в пакете тренировки? Не уверены, что это сработает для запуска тестов?

mornindew 26.10.2018 07:42

Обновил OP с дополнительным кодом, если это помогает, искренне цените ваши мысли здесь

mornindew 26.10.2018 07:42

Хм, тогда это сложнее, функция init в пакете событий будет вызываться только тогда, когда что-то вызывает событие, поэтому, если первый вызов в вашей системе идет на тренировку, тогда не будет триггера для настройки этой переменной. Другой вариант - иметь третий пакет, на который полагаются как мероприятие, так и тренировка, который просто содержит функцию GetEventByDate.

Iain Duncan 26.10.2018 07:53

Большое тебе спасибо. Это объясняет, почему у меня возникла проблема с работой интерфейса. Я ценю вашу помощь. Это многое прояснило.

mornindew 26.10.2018 16:43

Другие вопросы по теме