Alt Text

Uma struct, ou estrutura, é um tipo de dados personalizado que nos permite nomear e criar um conjunto de vários valores relacionados que compõem um grupo de dados. Se você estiver familiarizado com uma linguagem orientada a objeto, um struct é como os atributos de dados de um objeto.

Existe três tipos de estruturas que são:

  • Estrutura de tuplas que são, basicamente denominadas por tuplas.
  • Temos aquela clássica estrutura do C.
  • Temos a estrutura de unidade, que são sem campo, são uteis para os genéricos.

struct Tuplestruct(i32, i32);
 
fn main() {
  let number = Tuplestruct(10, 20);
  // Destructure
  let Tuplestruct(x, y) = number;
  println!("x: {}, y: {}", x, y);
}


/*
  x: 10, y: 20
*/

Código acima temos uma estrutura com tuplas. Criamos struct na linha 2 informando que terá dois números inteiros, dentro da função main importamos dois números para estrutura após a importação retiramos o mesmo da estrutura e imprimimos abaixo. Nesse exemplo temos uma estrutra de tuplas de uma forma simples.


struct NormalStruct {
  a: i32,
  b: i32,
}

fn main() {
  let ns = NormalStruct { a: 1, b: 2 };
  // Destructure
  let NormalStruct { a, b } = ns;
  println!("a: {}, b: {}", a, b)
}

/*
  a: 1, b: 2
*/

Código acima temos uma estrutura comum, criamos uma structs na linha 2 informando que teremos a e b sendo inteiros, dentro da função main importamos números a e b com os números após retiramos os valores da estrutura e imprimimos abaixo.

Mas realmente, como podemos usar isso de forma útil ?


#[derive(Debug)]
struct User {
  username: String,
  email: String,
  active: bool,
}

fn main() {
  let user = build_user(
    String::from("contato@higordiego.com.br"),
    String::from("Higor Diego"),
  );
  println!("email: {}, active: {}", user.email, user.active);
}

fn build_user(email: String, username: String) -> User {
  User {
    username: username,
    email: email,
    active: true,
  }
}
/*
  email: contato@higordiego.com.br, active: true
*/

Então, vamos pensar da seguinte forma, o código acima tem estrutura para receber usuários, o struct possui atributos de um sistema simples onde temos o nome e email e se o usuário está ativo ou não no sistema. Criamos uma função para gerar esse usuário retornando sua estrutura e após isso na função main imprimimos os valores contidos.

Se parar para pensar um pouco esse struct lembra um modelo ou esquema de um ORM isso é muito familiar para as pessoas que já desenvolvem.

Vamos para um exemplo prático.

Iremos fazer uma chamada nessa API http://ip-api.com/json/187.19.230.194 o retorno dela vem com um JSON da seguinte forma.

{
    "as": "AS28126 BRISANET SERVICOS DE TELECOMUNICACOES LTDA",
    "city": "Jaguaribe",
    "country": "Brazil",
    "countryCode": "BR",
    "isp": "Brisanet Servicos De Telecomunicacoes Ltda",
    "lat": -6.05537,
    "lon": -38.506,
    "org": "Brisanet Servicos De Telecomunicacoes Ltda",
    "query": "187.19.230.194",
    "region": "CE",
    "regionName": "Ceará",
    "status": "success",
    "timezone": "America/Fortaleza",
    "zip": "63475-000"
}

Iremos criar uma struct que armazena alguns dados desse retorno, segue o exemplo abaixo.


extern crate reqwest;
use serde::{Deserialize};

#[derive(Debug)]
#[derive(Deserialize)]
struct Information {
    city: String,
    country: String
}

fn main() -> Result<(), Box<std::error::Error>> {
  let resp: Information = reqwest::get("http://ip-api.com/json/187.19.230.194")?.json()?;
  println!("city: {}", resp.city);
  println!("country: {}", resp.country);
  Ok(())
}

/*
  city: Jaguaribe
  country: Brazil
*/

No código acima requisitamos a url usando um pacote chamado request com o método GET informamos que o retorno será em json, após o retorno injetamos os dados no struct e com esse dados pegamos dois atributos daquele json que é o city e country, e por fim imprimimos no console.

O struct é muito útil para estruturar os seus dados, vamos utilizar ele bastante aqui nos próximos posts.

Então galera é isso, espero que tenham gostado até a próxima.