Rust - Ownership ?
Tags: rust, ownership, introduction, developer
Published: 2021-09-26 18:12:19


![alt text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/54uwwixau0cwypypc1st.png)

Todos os programas têm que decidir de que forma vão utilizar a memória do computador durante sua execução.

Existe linguagens que abordam o garbage collection (coleta de lixo) que simplesmente buscam espaço em memória que não estão em uso naquele momento.

Outra abordagem em outras linguagens é que, o programador deve alocar o espaço em memória e liberar.

No Rust usa uma abordagem diferente que é memória gerenciada através de um sistema de posse que contém um conjunto de regras que isso é verificado em tempo de compilação.

### Regras de Owneship

- Cada valor em Rust possui uma variável que é dita seu owner (sua dona).
- Pode apenas haver um owner por vez.
- Quando o owner sai fora de escopo, o valor será destruído.

Para que possamos ilustrar o conjunto de regras precisamos de um tipo de dados que seja complexo abordagem porque esses dados são armazenados na pilha e assim retirada quando o escopo acaba.

Vamos para o exemplo.


```rust

fn main() {

    let x =  String::from("Higor Diego");
    println!("{}", x);

}

/*
  Higor Diego  
*/

```

Em post anteriores vimos string literais onde o valor da string é fixado elas são convenientes mas se adequam em situação que queremos textos em nossos programas. Uma das característica delas que são imutáveis.

No exemplo usamos o *String::From o ::* é um operador que nos permiti indicar o namespace da função *from* que se caracteriza como uma string.

Vamos para o exemplo abaixo.

```rust


fn main() {

    let mut x  =  String::from("Higor Diego");
    x.push_str(" é o meu nome");
    println!("{}", x);

}

/*
  Higor Diego é o meu nome
*/

```

Fica uma pergunta no ar, *porque as String* podem ser *alterada e as literais não*? O detalhe disso é como eles lidam com a memória.

Quando uma String literal é declarada já está explícito o conteúdo com isso injetado no software assim fazendo elas serem rápidas.

Segue o exemplo.

```rust

{
  let x = String::from("escopo");
}

```

No exemplo acima temos um escopo que é declarado pela chaves dentro dele temos uma variável x que é uma string após o fechamento da chaves a variável não é mais valida pois o escopo fechou.

No Rust quando a variável sai do escopo automaticamente chamamos uma função especial chamada drop. Parece simples mas quando temos múltiplas variáveis como seria ?

Segue o exemplo.

```rust

fn main() {
    let number_1 = 10;
    let number_2 = number_1;
}

```

No caso acima temos uma variável chamada *number_1* que recebe um valor de 10 e temos *number_2* que associada a variável anterior. Temos duas variáveis com o mesmo valor isso acontece porque números possuem um tamanho fixo.

No caso de uma String como seria ?

```rust

fn main() {
    let n_1 = String::from("higor");
    let n_2 = n_1;

    println!("{}", n_1);
}

/*
     --> main.rs:27:20
   |
25 |     let n_2 = n_1;
   |         --- value moved here
26 | 
27 |     println!("{}", n_1)
   |                    ^^^ value used here after move
   |
   = note: move occurs because `n_1` has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error

*/

```

Se analisar o exemplo anterior com esse, seria basicamente a mesma coisa só que existe uma diferença, porque estamos falando de *"cópia rasa"* e *"copia profunda"*.

O Rust nesse exemplo está invalidando a primeira variável no lugar de chamar a *"copia rasa"* isso é conhecido como move. Após a locação da variável para *n_2* com *n_1* o Rust libera o espaço de valor da *n_1* em memória e a loca *n_2* no seu lugar assim invalidando a variável *n_1*.

Para resolução vamos utilizar uma função chamada *clone()* que no caso seria uma copia profunda da variável declarada.


Segue o exemplo.

```rust

fn main() {
    let n_1 = String::from("higor");
    let n_2 = n_1.clone();

    println!("n_1: {}, n_2: {}", n_1, n_2);
}

/*
  n_1: higor, n_2: higor
*/


```

Vamos testar o mesmo conceito com funções.

```rust

fn main() {
  let x1 = retorna_string();
  let x2 = x1;
  println!("x1: {}, x2: {}", x1, x2);
}

fn retorna_string() -> String {
  return String::from("olá");
}
/*
 --> main.rs:4:30
  |
3 |   let x2 = x1;
  |       -- value moved here
4 |   println!("x1: {}, x2: {}", x1, x2);
  |                              ^^ value used here after move
  |
  = note: move occurs because `x1` has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error
*/

```

*Ahhhhh*, mas está fácil. Para que possa corrigir só usar o *clone()*.

Segue o exemplo.

```rust

fn main() {
  let x1 = retorna_string();
  let x2 = x1.clone();
  println!("x1: {}, x2: {}", x1, x2);
}

fn retorna_string() -> String {
  return String::from("olá");
}

*/
  x1: olá, x2: olá
*/

```

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