Как получить «дескриптор» канала без связанного типа

#go #channel

#Вперед #канал

Вопрос:

У меня есть серверная часть (Go server), которая обслуживает несколько интерфейсов (веб-страниц), и все запросы / ответы обрабатываются через каналы определенных типов. Например, каждый интерфейс связан (на серверной части) с каналом, по которому отправляются ответы (type = chan<- Response).

Недавно я внедрил систему входа в систему, где каждый интерфейс связан с идентификатором пользователя. Для отслеживания пользователей у меня есть карта:

 logins map[chan<- Response]LoginData
  

Используя это, я могу быстро искать вещи, связанные с интерфейсом, такие как разрешения. Все это работает нормально.

Однако, чтобы все было более безопасным и модульным, я перенес все элементы входа в систему в отдельный пакет. Все это работает, за исключением одной ошибки — карта логинов вводится с помощью типа «chan<- Response», но тип ответа определен в моем основном пакете, и я не хочу предоставлять его для пакета Login. (Я не думаю, что я мог бы в любом случае, поскольку это создало бы циклическую ссылку.)

Я только хочу использовать «chan<- Response» в качестве типа дескриптора в пакете входа — мне не нужно писать на этот канал оттуда. Я попытался преобразовать канал в небезопасный.Указатель, но это не разрешено компилятором. С другой стороны, я не могу использовать указатель на переменную канала (*chan<- Response) в качестве дескриптора, поскольку канал хранится в нескольких местах, поэтому переменная канала будет иметь разные адреса.

Я также пробовал выполнять приведение к другому типу канала, такому как chan int и chan interface{}, но компилятору это не нравится. Похоже, не существует никакого способа преобразовать канал в «универсальный» канал.

Мне действительно просто нужен адрес внутренних данных канала — как вы получаете при fmt.Выведите канал с помощью %v. Лучшее, что я могу придумать, это использовать строку, подобную этой:

 var c chan<- Response = ...
var userID = "steve"
loginKey = fmt.Sprint(c)
Login.Add(loginKey, userID)
  

Я не уверен, что это допустимо, но, похоже, работает, но мне кажется, должен быть лучший способ.

Комментарии:

1. Вы могли бы использовать interface {} в качестве типа

2. «тип ответа определен в моем основном пакете» — это недостаток дизайна. main Пакет должен делать как можно меньше, и он определенно не должен определять типы, именно по той причине, которую вы видите здесь.

3. Спасибо @Adrian за чтение и понимание (а не за голосование «против», что, на мой взгляд, является разумным вопросом :). Я абсолютно согласен с вашим комментарием, но этот проект начинался как один основной пакет и рос. Я пытался разделить его части на внутренние пакеты (как в этом вопросе) Я прислушаюсь к вашему совету и попытаюсь разобраться, как переместить типы в отдельные пакеты.

Ответ №1:

С другой стороны, я не могу использовать указатель на переменную канала (*chan<- Response) в качестве дескриптора, поскольку канал хранится в нескольких местах, поэтому переменная канала будет иметь разные адреса.

Но это единственное (наполовину приемлемое решение): передавайте не chan Response , а *(chan Response) (добавляя указания по своему вкусу). Все остальное дерьмо. Лучшее, что можно сделать, это скрыть этот ответ канала в типе.

Комментарии:

1. Спасибо. Вы правы, должно быть достаточно просто иметь одну переменную chan и передавать указатель на нее. Это просто кажется немного избыточным, поскольку я думаю, что переменная канала по сути является просто указателем на реальный канал. Я согласен, что лучше всего создать новый тип, но нет смысла объявлять его в моем пакете входа, и я не могу объявить его в основном пакете (циклическая ссылка), поэтому, я думаю, мне нужно поместить его в новый пакет, который я импортирую в пакеты main и Login.