Макроусловия выбора Токио и оценка руки

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

Я написал код раньше и (наивно) использовал условия в макросе tokio select. К сожалению, я быстро понял, что макрос сначала оценит руку (чтобы получить будущее) и только после этого проверит условие и на основе этого условия либо запустит будущее, либо пропустит его.

В результате, когда я запускаю этот код, я получаю: thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:16:35

use tokio::io::AsyncReadExt;
use tokio::net::TcpStream;

#[tokio::main]
async fn main() {
    let mut stream1 : TcpStream = TcpStream::connect("info.cern.ch:80").await.unwrap();
    let mut stream2 : Option<TcpStream> = None;
    let mut buf = vec![0_u8; 1024];
    let mut buf2 = vec![0_u8; 1024];
    
    tokio::select! {
        result = stream1.read(&mut buf) => {
            // do something here
        }
        
        result = stream2.as_mut().unwrap().read(&mut buf2), if stream2.is_some() => {
            // do somethihng here
        }
    }
    
}

Вопрос, который у меня есть, как справиться с этим?

Я наткнулся на следующие идеи, и я не доволен ни одной из них

  • Добавьте оператор if. Если stream2.is_some(), то выберите двумя руками, в противном случае выберите с одной меткой. Это работает, но приводит к довольно уродливому дублированию кода.

  • Я посмотрел в направлении FutureUnordered. Однако, принимая во внимание, что приведенный выше код будет выполняться в цикле, я отказался от этого подхода, потому что мне не понравилось, что я пытаюсь заимствовать вещи как изменяемые в цикле.

  • Я думал использовать «поддельный» TcpStream, просто чтобы удалить часть Option<>. Однако это тоже выглядит некрасиво.

Я ищу способ, который позволит мне сохранить этот выбор! над опцией

Похоже, это поведение изменилось. Старая версия документов: «Кроме того, каждая ветвь может включать необязательное предварительное условие if. Это предварительное условие оценивается как до<async expression>. Если предварительное условие возвращает false, ветвь полностью отключена». Но текущая версия: «Кроме того, каждая ветвь может включать необязательное предварительное условие if. Если предварительное условие возвращает false, то ветвь отключается. Предоставленное <async expression> все еще оценивается, но результирующее будущее никогда не опрашивается».

cdhowie 17.05.2022 00:52

Это немного странно для меня, и мне любопытно, почему они сделали это изменение. Поведение старой версии имеет для меня гораздо больше смысла.

cdhowie 17.05.2022 00:53

@cdhowie Я никогда не использовал старую версию. Однако я согласен, что старое поведение имело больше смысла.

Victor Ronin 17.05.2022 03:37
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
3
35
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вы можете перенести обработку потока optiona в другое будущее, возможно, возвращая пользовательскую ошибку. Затем сопоставление шаблона при успешном чтении:

use tokio::io::AsyncReadExt;
use tokio::net::TcpStream;
use std::io::{Error, ErrorKind};

#[tokio::main]
async fn main() {
    let mut stream1 : TcpStream = TcpStream::connect("info.cern.ch:80").await.unwrap();
    let mut stream2 : Option<TcpStream> = None;
    let mut buf = vec![0_u8; 1024];
    let mut buf2 = vec![0_u8; 1024];
    
    let read2 = async move {
        match stream2 {
            Some(mut stream) => stream.read(&mut buf2).await,
            _ => Err(Error::new(ErrorKind::Other, "No available stream")),
        }
    };
    
    tokio::select! {
        result = stream1.read(&mut buf) => {
            // do something here
        }
        
        Ok(result) = read2 => {
            // do somethihng here
        }
    }
    
}

Детская площадка

Если вам не нравится пользовательская ошибка, вы можете перевернуть все в Option<Result> и сопоставить все с шаблоном:

...
    let read2 = async move {
        match stream2 {
            Some(mut stream) => Some(stream.read(&mut buf2).await),
            None => None,
        }
    };
    
    tokio::select! {
        result = stream1.read(&mut buf) => {
            // do something here
        }
        
        Some(result) = read2 => {
            // do somethihng here
        }
    }
...

Детская площадка

Спасибо @Netwave. Это именно то, что я искал. Я пошел на прогулку, и у меня возникла похожая идея, и было удивительно вернуться и увидеть, что у вас есть полное решение.

Victor Ronin 16.05.2022 23:39

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