de-vraag
  • Pertanyaan
  • Tag
  • Pengguna
Notifikasi
Imbalan
Registrasi
Setelah Anda mendaftar, Anda akan diberitahu tentang balasan dan komentar untuk pertanyaan Anda.
Gabung
Jika Anda sudah memiliki akun, masuk untuk memeriksa pemberitahuan baru.
Akan ada hadiah untuk pertanyaan, jawaban, dan komentar tambahan.
Lebih
Sumber
Sunting
Brian Oh
Brian Oh
Question

Adalah mungkin untuk menggunakan variabel global dalam Karat?

Saya tahu bahwa secara umum, global-variabel yang harus dihindari. Namun demikian, saya pikir dalam arti praktis, hal ini kadang-kadang diinginkan (dalam situasi di mana variabel merupakan bagian integral dari program) untuk menggunakannya.

Dalam rangka untuk belajar Karat, I'm sedang menulis sebuah basis data menguji program dengan menggunakan sqlite3 dan Karat/sqlite3 paket di GitHub. Akibatnya, yang mengharuskan (di tes saya-program) (sebagai alternatif untuk variabel global), untuk lulus database variabel antara fungsi-fungsi yang ada sekitar selusin. Contoh di bawah ini.

  1. Adalah hal yang mungkin dan layak dan diinginkan untuk menggunakan variabel global dalam Karat?

  2. Diberikan contoh di bawah ini, saya bisa menyatakan dan menggunakan variabel global?

extern crate sqlite;

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

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

Aku mencoba mengikuti, tapi itu doesn't tampaknya cukup tepat dan mengakibatkan kesalahan-kesalahan di bawah ini (saya mencoba juga dengan sebuah tidak aman block):

extern crate sqlite;

static mut DB: Option<sqlite::Connection> = None;

fn main() {
    DB = sqlite::open("test.db").expect("Error opening test.db");
    println!("Database Opened OK");

    create_table();
    println!("Completed");
}

// Create 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 created"),
        Err(err) => println!("Exec of Sql failed : {}\nSql={}", err, sql),
    }
}

Kesalahan yang dihasilkan dari kompilasi:

error[E0308]: mismatched types
 --> src/main.rs:6:10
  |
6 |     DB = sqlite::open("test.db").expect("Error opening test.db");
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `sqlite::Connection`
  |
  = note: expected type `std::option::Option<sqlite::Connection>`
             found type `sqlite::Connection`

error: no method named `exec` found for type `std::option::Option<sqlite::Connection>` in the current scope
  --> src/main.rs:16:14
   |
16 |     match DB.exec(sql) {
   |              ^^^^
78 2013-10-26T09:39:45+00:00 4
 Shepmaster
Shepmaster
Pertanyaan edit 5 Maret 2017 в 3:06
Pemrograman
rust
global-variables
Ercan Erden
Ercan Erden
26 Oktober 2013 в 4:20
2013-10-26T16:20:34+00:00
Lebih
Sumber
Sunting
#22627294

It's mungkin tapi tidak ada tumpukan alokasi diperbolehkan langsung. Alokasi timbunan dilakukan pada saat runtime. Berikut ini adalah beberapa contoh:

static SOME_INT: i32 = 5;
static SOME_STR: &'static str = "A static string";
static SOME_STRUCT: MyStruct = MyStruct {
    number: 10,
    string: "Some string",
};
static mut db: Option<sqlite::Connection> = None;

fn main() {
    println!("{}", SOME_INT);
    println!("{}", SOME_STR);
    println!("{}", SOME_STRUCT.number);
    println!("{}", SOME_STRUCT.string);

    unsafe {
        db = Some(open_database());
    }
}

struct MyStruct {
    number: i32,
    string: &'static str,
}
Felix Rabe
Felix Rabe
Jawaban edit 18 Juni 2019 в 7:34
43
0
 Shnatsel
Shnatsel
5 Maret 2017 в 5:29
2017-03-05T05:29:25+00:00
Lebih
Sumber
Sunting
#22627296

Anda dapat menggunakan variabel statis cukup mudah asalkan mereka thread-lokal.

The downside adalah bahwa objek tidak akan terlihat oleh thread lain program anda mungkin bertelur. Keuntungannya adalah bahwa tidak seperti benar-benar global negara, hal ini sepenuhnya aman dan tidak sakit untuk menggunakan - benar global negara besar yang sakit dalam bahasa apapun. Berikut ini's contoh:

extern mod sqlite;

use std::cell::RefCell;

thread_local!(static ODB: RefCell<sqlite::database::Database> = RefCell::new(sqlite::open("test.db"));

fn main() {
    ODB.with(|odb_cell| {
        let odb = odb_cell.borrow_mut();
        // code that uses odb goes here
    });
}

Di sini kita membuat sebuah thread-lokal variabel statis dan kemudian menggunakannya dalam fungsi. Perhatikan bahwa itu adalah statis dan tidak berubah; ini berarti bahwa alamat di mana ia berada adalah kekal, tapi berkat RefCell nilai itu sendiri akan bisa berubah.

Tidak seperti biasa statis, dalam thread-lokal!(statis ...) anda dapat membuat cukup banyak objek sewenang-wenang, termasuk orang-orang yang membutuhkan tumpukan alokasi untuk inisialisasi seperti Vec, HashMap dan lain-lain.

Jika anda tidak dapat menginisialisasi nilai langsung, misalnya, itu tergantung pada input pengguna, anda mungkin juga harus membuang Pilihan di sana, dalam hal mengakses itu mendapat sedikit berat:

extern mod sqlite;

use std::cell::RefCell;

thread_local!(static ODB: RefCell<Option<sqlite::database::Database>> = RefCell::New(None));

fn main() {
    ODB.with(|odb_cell| {
        // assumes the value has already been initialized, panics otherwise
        let odb = odb_cell.borrow_mut().as_mut().unwrap();
        // code that uses odb goes here
    });
}
 cloudcalvin
cloudcalvin
Jawaban edit 18 Maret 2017 в 10:15
28
0
 AbbasFaisal
AbbasFaisal
20 Mei 2016 в 11:25
2016-05-20T11:25:25+00:00
Lebih
Sumber
Sunting
#22627295

Lihat const dan statis bagian dari Karat pesan.

Anda dapat menggunakan sesuatu seperti berikut:

const N: i32 = 5; 

atau

static N: i32 = 5;

di ruang global.

Tapi ini tidak bisa berubah. Untuk berubah-ubah, anda bisa menggunakan sesuatu seperti:

static mut N: i32 = 5;

Kemudian referensi mereka seperti:

unsafe {
    N += 1;

    println!("N: {}", N);
}
 Shepmaster
Shepmaster
Jawaban edit 20 Mei 2016 в 12:36
16
0
Yifan Sun
Yifan Sun
25 Januari 2019 в 8:55
2019-01-25T20:55:05+00:00
Lebih
Sumber
Sunting
#22627297

Saya tidak tahu mengapa tidak ada yang berbicara tentang solusi yang menggunakan Arc. Saya juga baru Karat, tapi ini sepertinya solusi ini bekerja.

``karat

[macro_use]

extern peti lazy_static;

menggunakan std::sync::{Arc, Mutex};

lazy_static! { statis ref GLOBAL: Arc<Mutex = Arc::new(Mutex::new(GlobalType::new())); } ``

Juga, solusi lain adalah untuk menyatakan palang saluran tx/rx pasangan abadi variabel global. Saluran harus dibatasi dan hanya bisa menampung 1 elemen. Ketika anda menginisialisasi variabel global, push contoh global ke dalam saluran. Bila menggunakan variabel global, pop channel untuk memperoleh itu dan mendorongnya kembali setelah selesai menggunakannya.

Kedua solusi harus memberikan Karat aman pendekatan untuk menggunakan variabel global.

Yifan Sun
Yifan Sun
Jawaban edit 17 Maret 2019 в 1:54
2
0
Tambahkan pertanyaan
Kategori
Semua
Teknologi
Budaya / Rekreasi
Kehidupan / Seni
Ilmu Pengetahuan
Profesional
Bisnis
Pengguna
Semua
Baru
Populer
1
Галина Утяшова
Terdaftar 21 jam yang lalu
2
Asilbek Qadamboyev
Terdaftar 4 hari yang lalu
3
Akshit Mehta
Terdaftar 6 hari yang lalu
4
me you
Terdaftar 1 minggu yang lalu
5
Никита иванов
Terdaftar 1 minggu yang lalu
ID
JA
KO
RU
© de-vraag 2022
Sumber
stackoverflow.com
di bawah lisensi cc by-sa 3.0 dengan atribusi