Reputation: 2012
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
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
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
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