221 votes

Est-il possible d'utiliser des variables globales en Rust ?

Je sais qu'en général, il est recommandé d'éviter les variables globales. Néanmoins, je pense qu'en pratique, il est parfois souhaitable (dans des situations où la variable est essentielle pour le programme) de les utiliser.

Pour apprendre Rust, j'écris actuellement un programme de test de base de données en utilisant sqlite3 et le package Rust/sqlite3 sur GitHub. En conséquence, cela nécessite (dans mon programme de test) (comme alternative à une variable globale), de passer la variable de base de données entre les fonctions dont il y en a environ une douzaine. Un exemple est donné ci-dessous.

  1. Est-il possible, réalisable et souhaitable d'utiliser des variables globales en Rust ?

  2. Étant donné l'exemple ci-dessous, puis-je déclarer et utiliser une variable globale ?

    extern crate sqlite;

    fn main() { let db: sqlite::Connection = open_database();

    if !insert_data(&db, insert_max) {
        return;
    }

    }

J'ai essayé ce qui suit, mais cela ne semble pas être tout à fait correct et a donné les erreurs ci-dessous (j'ai également essayé avec un bloc unsafe) :

extern crate sqlite;

static mut DB: Option = None;

fn main() {
    DB = sqlite::open("test.db").expect("Erreur à l'ouverture de test.db");
    println!("Base de données ouverte avec succès");

    create_table();
    println!("Terminé");
}

// Créer la table
fn create_table() {
    let sql = "CREATE TABLE IF NOT EXISTS TEMP2 (ikey INTEGER PRIMARY KEY NOT NULL)";
    match DB.exec(sql) {
        Ok(_) => println!("Table créée"),
        Err(err) => println!("Exécution du SQL échouée : {}\nSql={}", err, sql),
    }
}

Erreurs résultant de la compilation :

erreur[E0308]: types incompatibles
 --> src/main.rs:6:10
  |
6 |     DB = sqlite::open("test.db").expect("Erreur à l'ouverture de test.db");
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type attendue `std::option::Option`, trouvé `struct sqlite::Connection`
  |
  = note: type attendue `std::option::Option`
             type trouvée `sqlite::Connection`

erreur: aucune méthode nommée `exec` trouvée pour le type `std::option::Option` dans la portée actuelle
  --> src/main.rs:16:14
   |
16 |     match DB.exec(sql) {
   |              ^^^^

15voto

messy_tech Points 523

entrer la description de l'image ici

Je pense que cette page couvre la plupart des aspects de manière approfondie https://www.sitepoint.com/rust-global-variables/

11voto

at54321 Points 239

À partir de Rust 1.70, il y a aussi le primitif de synchronisation OnceLock que nous pourrions utiliser dans les cas où nous avons juste besoin d'une variable globale statique qui est initialisée (écrite) une seule fois.

Voici un exemple d'un HashMap global statique en lecture seule :

use std::collections::HashMap;
use std::sync::OnceLock;

static GLOBAL_MAP: OnceLock> = OnceLock::new();

fn main() {
    let m = get_hash_map_ref();
    assert_eq!(m.get("five"), Some(&5));
    assert_eq!(m.get("seven"), None);
    std::thread::spawn(|| {    
        let m = get_hash_map_ref();
        println!("From another thread: {:?}", m.get("five"));
    }).join().unwrap();
}

fn get_hash_map_ref() -> &'static HashMap {
    GLOBAL_MAP.get_or_init(|| {
        create_fixed_hash_map()
    })
}

fn create_fixed_hash_map() -> HashMap {
    let mut m = HashMap::new();
    m.insert("five".to_owned(), 5);
    m.insert("ten".to_owned(), 10);
    m
}

Comme on peut le voir, cette carte peut être accédée à partir de différents threads.

Notez que HashMap::new() n'est pas const (du moins pas encore) et c'est pourquoi nous ne pouvons (toujours) pas avoir quelque chose comme const MY_MAP: HashMap<...> = ... en Rust.

2voto

Jermyn Xia Points 87

Utilisez la crate once_cell ou lazy_static, ou SyncOnceCell en mode nightly.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X