Palash Nigam
Palash Nigam

Reputation: 2012

How to set a field in a struct with an empty value?

I am writing a TCP client and have a conn field in my client struct. My client implements two methods new to instantiate the struct and connect to open a connection to the server and set that as the value of the conn field

pub struct FistClient {
    addr: String,
    conn: TcpStream,
}

impl FistClient {
    pub fn new(ip: &str, port: &str) -> Self {
        FistClient {
            addr: String::from(ip) + ":" + &String::from(port),
            // conn: <some-defaullt-value>,
        }
    }

    pub fn connect(&mut self, ip: &str, port: &str) {
        let res = TcpStream::connect(&self.addr);
        match res {
            Ok(c) => self.conn = c,
            Err(_) => panic!(),
        }
    }
}

I want to set the conn field in the new method to some default value. In Go I can do something like conn: nil but it doesn't work here. I tried Default::default() too but that trait isn't implemented for TCPStream how should I set it to a default value?

Upvotes: 18

Views: 38587

Answers (3)

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382160

There's no null in Rust (and no Null Pointer Exception, Rust is designed for safety).

You must either

1) use an option (i.e. a field of type Option<TcpStream>)

2) or better: return a result when building the struct

Here, the best option would probably be to connect from inside a function returning a Result<FistClient>, so that you don't have to check whether your struct has a valid stream.

I would do something like this:

pub struct FistClient {
    addr: String,
    conn: TcpStream,
}

impl FistClient {
    pub fn new(ip: &str, port: &str) -> Result<Self> {
        let addr = format!("{}:{}", ip, port);
        let conn = TcpStream::connect(&addr)?;
        Ok(FistClient { addr, conn })
    }
}

Side note: It's really preferable to not build your applications with calls to panic, even when you think you're just building a dirty draft. Handle errors instead.

Upvotes: 31

Peter Hall
Peter Hall

Reputation: 58735

In Rust, the idea of null is modelled with Option. You give a field the type Option<TcpStream> to indicate that it might not be there (None), or be a valid value (Some(TcpStream)).

pub struct FistClient {
    addr: String,
    conn: Option<TcpStream>,
}

impl FistClient {
    pub fn new(ip: &str, port: &str) -> Self {
        FistClient {
            addr: String::from(ip) + ":" + &String::from(port),
            conn: None,
        }
    }

    pub fn connect(&mut self, ip: &str, port: &str) {
        let res = TcpStream::connect(&self.addr);
        match res {
            Ok(c) => self.conn = Some(c),
            Err(_) => panic!(),
        }
    }
}

Upvotes: 13

S&#233;bastien Renauld
S&#233;bastien Renauld

Reputation: 19662

You will need to change your type to Option<TCPStream> if you would like to keep this call pattern. an Option expresses the possible lack of a value (I. e. null) with two enum variants: Some(_) and None.

Once you have this in place you can easily retrieve a mutable reference to the inner member by calling as_mut to retrieve an Option<&mut T>.

Upvotes: 5

Related Questions