Статические переменные, которые зависят от среды - PullRequest
0 голосов
/ 23 июня 2018

У меня есть структура, которая должна быть инициирована один раз с некоторым значением, а затем на нее можно свободно ссылаться (или даже делиться между потоками) без проблем. Проблема в том, что я хочу использовать его в обработчике hyper обратного вызова. Вот мой пример кода:

extern crate futures; // 0.1.1
extern crate hyper; // 0.12

use std::net::SocketAddr;
use hyper::service::service_fn;
use hyper::{Body, Request, Response, Server};
use futures::prelude::*;

fn main() {
    let token = std::env::args().next().unwrap();
    run(&token, "127.0.0.1:8080");
}

fn run(bot_token: &str, listening_address: &str) {
    let addr: SocketAddr = listening_address.parse().unwrap();

    let server = Server::bind(&addr)
        .serve(move || service_fn(|x| echo(x, bot_token)));
}

fn echo(
    req: Request<Body>,
    bot_token: &str
) -> impl Future<Item = Response<Body>, Error = hyper::Error> + Send {
    futures::future::ok(Response::new(Body::empty()))
}

Проблема здесь в том, что hyper требует, чтобы обратный вызов был static:

error[E0621]: explicit lifetime required in the type of `bot_token`
  --> src\main.rs:18:10
   |
14 | fn run(bot_token: &str, listening_address: &str) {
   |        --------- consider changing the type of `bot_token` to `&'static str`
...
18 |         .serve(move || service_fn(|x| echo(x, bot_token)))
   |          ^^^^^ lifetime `'static` required

error[E0621]: explicit lifetime required in the type of `bot_token`
  --> src\main.rs:19:10
   |
14 | fn run(bot_token: &str, listening_address: &str) {
   |        --------- consider changing the type of `bot_token` to `&'static str`
...
19 |         .map_err(|e| eprintln!("server error: {}", e));
   |          ^^^^^^^ lifetime `'static` required

Если я буду следовать этому совету и изменить telegram_client время жизни на static, я получу ошибку, что замыкание может пережить run функцию.

Как мне этого избежать? Я обнаружил, что могу заставить его работать следующим образом:

fn run(bot_token: &str, listening_address: &str) {
    let addr: SocketAddr = listening_address.parse().unwrap();

    let bot_token = Arc::new(bot_token.to_string());
    let server = Server::bind(&addr)
        .serve(move || {
            let bot_token = bot_token.clone();
            service_fn(move |x| echo(x, bot_token.clone()))
        });
}

fn echo(
    req: Request<Body>,
    bot_token: Arc<String>
) -> impl Future<Item = Response<Body>, Error = hyper::Error> + Send {
    futures::future::ok(Response::new(Body::empty()))
}

Но это выглядит странно, равно как и подсчет ссылок для ситуации, когда мы знаем, что не будем отбрасывать ссылку до завершения программы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...