Skip to content

Latest commit

 

History

History
214 lines (157 loc) · 6.51 KB

File metadata and controls

214 lines (157 loc) · 6.51 KB

2.4 struct

struct

Podemos definir novos tipos de contêineres de outras propriedades ou campos em Go exatamente como em outras linguagens de programação. Por exemplo, podemos criar um tipo chamado person com os campos name (nome) e age (idade) para representar uma pessoa. Chamamos este tipo de struct (estrutura).

type person struct {
    	name string
    	age int
}

Veja como é fácil definir uma struct!

Existem dois campos.

  • name é uma string usada para armazenar o nome da pessoa.
  • age é um int usado para armazenar a idade da pessoa.

Vamos ver como utilizar isto.

type person struct {
    	name string
    	age int
}

var P person  // p é do tipo person

P.name = "Astaxie"  // atribui "Astaxie" para o campo 'name' de p
P.age = 25  // atribui 25 para o campo 'age' de p
fmt.Printf("The person's name is %s\n", P.name)  // acessa o campo 'name' de p

Existem outras três maneiras de definir uma estrutura.

  • Atribuir os valores iniciais em ordem

      P := person{"Tom", 25}
  • Usar o formato field:value (campo:valor) para inicializar a estrutura sem ordem

      P := person{age:24, name:"Bob"}
  • Definir uma estrutura anônima e então inicializar ela

      P := struct{name string; age int}{"Amy",18}

Vejamos um exemplo completo.

package main
import "fmt"

// define um novo tipo
type person struct {
	name string
	age int
}

// compara a idade de duas pessoas e retorna dois valores: a pessoa mais velha e a diferença de idade
// estrutura é passada por valor
func Older(p1, p2 person) (person, int) {
	if p1.age>p2.age {  
    	return p1, p1.age-p2.age
	}
	return p2, p2.age-p1.age
}

func main() {
	var tom person

	// inicialização
	tom.name, tom.age = "Tom", 18

    // inicializa dois valores pelo formato "campo:valor"
	bob := person{age:25, name:"Bob"}

	// inicializa dois valores em ordem
	paul := person{"Paul", 43}

	tb_Older, tb_diff := Older(tom, bob)
	tp_Older, tp_diff := Older(tom, paul)
	bp_Older, bp_diff := Older(bob, paul)

	fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, bob.name, tb_Older.name, tb_diff)

	fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, paul.name, tp_Older.name, tp_diff)

	fmt.Printf("Of %s and %s, %s is older by %d years\n", bob.name, paul.name, bp_Older.name, bp_diff)
}

Campos incorporados em struct

Acabei de apresentar a você como definir uma estrutura com nomes de campos e tipos. Na verdade, Go suporta campos sem nomes, mas com tipos. Chamamos esses campos de campos incorporados (embedded fields).

Quando um campo incorporado é uma estrutura, todos os campos desta estrutura serão implicitamente campos da estrutura onde ela foi incorporada.

Vejamos um exemplo.

package main
import "fmt"

type Human struct {
	name string
	age int
	weight int
}

type Student struct {
	Human  // campo incorporado, significa que a estrutura Student inclui todos os campos que Human possui
	specialty string
}

func main() {
	// inicializa um estudante
	mark := Student{Human{"Mark", 25, 120}, "Computer Science"}

	// acessa os campos
	fmt.Println("His name is ", mark.name)
	fmt.Println("His age is ", mark.age)
	fmt.Println("His weight is ", mark.weight)
	fmt.Println("His specialty is ", mark.specialty)
	// modifica a especialidade
	mark.specialty = "AI"
	fmt.Println("Mark changed his specialty")
	fmt.Println("His specialty is ", mark.specialty)
	// modifica a idade
	fmt.Println("Mark become old")
	mark.age = 46
	fmt.Println("His age is", mark.age)
	// modifica o peso
	fmt.Println("Mark is not an athlet anymore")
	mark.weight += 60
	fmt.Println("His weight is", mark.weight)
}

Figure 2.7 Herança em Student e Human

Vimos que podemos acessar os campos idade e nome de Student exatamente como podemos em Human. É assim que os campos incorporados funcionam. É muito legal, não é? Espere, tem algo mais legal! Você pode até usar o Student para acessar o Human neste campo incorporado!

mark.Human = Human{"Marcus", 55, 220}
mark.Human.age -= 1

Todos os tipos em Go podem ser usados como campos incorporados.

package main
import "fmt"

type Skills []string

type Human struct {
	name string
	age int
	weight int
}

type Student struct {
	Human  // estrutura como campo incorporado
	Skills // string slice como campo incorporado
	int    // tipo embutido como campo incorporado
	specialty string
}

func main() {
	// inicializa o Student Jane
	jane := Student{Human:Human{"Jane", 35, 100}, specialty:"Biology"}
	// acessa os campos
	fmt.Println("Her name is ", jane.name)
	fmt.Println("Her age is ", jane.age)
	fmt.Println("Her weight is ", jane.weight)
	fmt.Println("Her specialty is ", jane.specialty)
	// modifica o valor do campo skill
	jane.Skills = []string{"anatomy"}
	fmt.Println("Her skills are ", jane.Skills)
	fmt.Println("She acquired two new ones ")
	jane.Skills = append(jane.Skills, "physics", "golang")
	fmt.Println("Her skills now are ", jane.Skills)
	// modifica o campo incorporado
	jane.int = 3
	fmt.Println("Her preferred number is", jane.int)
}

No exemplo acima, podemos ver que todos os tipos podem ser campos incorporados e podemos usar funções para operar sobre eles.

No entanto, existe mais um problema. Se Human possui um campo chamado phone e Student possui um campo com o mesmo nome, o que devemos fazer?

Go usa uma maneira muito simples para resolver isto. Os campos externos obtêm níveis de acesso superiores, o que significa que quando você acessa student.phone, você irá obter o campo chamado phone de Student, e não aquele definido na estrutura Human. Este recurso pode ser visto simplesmente como uma sobrecarga de campo (field overloading).

package main
import "fmt"

type Human struct {
	name string
	age int
	phone string  // Human possui o campo phone
}

type Employee struct {
	Human  // campo incorporado Human
	specialty string
	phone string  // phone em Employee
}

func main() {
	Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
	fmt.Println("Bob's work phone is:", Bob.phone)
	// acessa o campo phone em Human
	fmt.Println("Bob's personal phone is:", Bob.Human.phone)
}

Links