2013-10-26 14 views
40

मुझे पता है कि सामान्य रूप से, वैश्विक-चर से बचा जाना चाहिए। फिर भी, मुझे लगता है कि व्यावहारिक अर्थ में, कभी-कभी वांछनीय होता है (परिस्थितियों में जहां चर प्रोग्राम के अभिन्न अंग होते हैं) उनका उपयोग करने के लिए।जंग में वैश्विक चर का उपयोग करना संभव है?

जंग सीखने के लिए, मैं वर्तमान में sqlite3 और गिटहब पर जंग/sqlite3 पैकेज का उपयोग कर डेटाबेस परीक्षण प्रोग्राम लिख रहा हूं। नतीजतन, यह आवश्यक है (मेरे टेस्ट-प्रोग्राम में) (एक वैश्विक चर के विकल्प के रूप में), डेटाबेस वर्चुअल को पास करने के लिए, जिसमें लगभग एक दर्जन हैं। एक उदाहरण नीचे है।

  1. क्या जंग में वैश्विक चर का उपयोग करना संभव और व्यवहार्य और वांछनीय है?

  2. नीचे दिए गए उदाहरण को देखते हुए, क्या मैं एक वैश्विक चर घोषित कर सकता हूं?

extern crate sqlite; 

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

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

मैं निम्नलिखित की कोशिश की है, लेकिन यह बहुत सही प्रतीत नहीं होता है और (मैं एक unsafe ब्लॉक के साथ भी करने की कोशिश की) नीचे दी गई त्रुटियों के परिणामस्वरूप:

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), 
    } 
} 

संकलन के परिणामस्वरूप त्रुटियां:

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) { 
    |    ^^^^ 
+1

एक ** सुरक्षित ** समाधान के लिए, कृपया [मैं कैसे एक वैश्विक बनाऊँ देखें: यह उपयोगकर्ता इनपुट पर निर्भर करता है, आप भी वहाँ में Option फेंकने के लिए, जिस स्थिति यह थोड़ा बोझल हो जाता है तक पहुँचने में हो सकता है , परिवर्तनीय सिंगलटन?] (http://stackoverflow.com/q/27791532/155423)। 'Static mut' विकल्प के साथ – Shepmaster

उत्तर

20

यह संभव है लेकिन नहीं एपी आवंटन सीधे अनुमति दी। हीप आवंटन रनटाइम पर किया जाता है। यहां कुछ उदाहरण दिए गए हैं:

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, 
} 
+0

, क्या इसका मतलब यह है कि कनेक्शन का उपयोग करने वाले कोड के प्रत्येक टुकड़े को असुरक्षित के रूप में चिह्नित किया जाना चाहिए? – Kamek

10

const and static section of the Rust book पर देखें। वैश्विक अंतरिक्ष में

const N: i32 = 5; 

या

static N: i32 = 5; 

:

आप इस प्रकार कुछ का उपयोग कर सकते हैं।

लेकिन ये उत्परिवर्तनीय नहीं हैं। तब उन्हें पसंद संदर्भ

static mut N: i32 = 5; 

: अस्थिरता के लिए, आप की तरह कुछ इस्तेमाल कर सकते हैं

unsafe { 
    N += 1; 

    println!("N: {}", N); 
} 
10

आप काफी आसानी से जब तक वे धागे की स्थानीय हैं स्थैतिक चर का उपयोग कर सकते हैं।

नकारात्मकता यह है कि ऑब्जेक्ट अन्य प्रोग्रामों के लिए दिखाई नहीं देगा जो आपके प्रोग्राम को उत्पन्न हो सकते हैं। उलझन यह है कि वास्तव में वैश्विक स्थिति के विपरीत, यह पूरी तरह से सुरक्षित है और इसका उपयोग करने में दर्द नहीं है - वास्तविक वैश्विक स्थिति किसी भी भाषा में भारी दर्द है। यहां एक उदाहरण दिया गया है:

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 
    }); 
} 

यहां हम एक थ्रेड-स्थानीय स्थैतिक चर बनाते हैं और फिर इसे फ़ंक्शन में उपयोग करते हैं। ध्यान दें कि यह स्थैतिक और अपरिवर्तनीय है; इसका मतलब यह है कि जिस पते पर यह रहता है वह अपरिवर्तनीय है, लेकिन RefCell के लिए धन्यवाद मूल्य स्वयं ही परिवर्तनीय होगा।

नियमित static के विपरीत, thread-local!(static ...) में आप उन है कि प्रारंभ जैसे Vec, HashMap और दूसरों के लिए ढेर आवंटन की आवश्यकता सहित काफी मनमाने ढंग से वस्तुओं, बना सकते हैं।

यदि आप तुरंत मूल्य प्रारंभ नहीं कर सकते हैं, उदा।

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 
    }); 
} 
संबंधित मुद्दे