Skip to content

Commit a139135

Browse files
authored
Merge pull request astaxie#847 from yaBliznyk/patch-2
Update 02.4.md
2 parents aac6e28 + bf39135 commit a139135

File tree

1 file changed

+159
-159
lines changed

1 file changed

+159
-159
lines changed

ru/02.4.md

+159-159
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
## struct
44

55
В Go мы можем определять новые типы контейнеров свойств или полей так же, как и в других языках программирования. Например, чтобы описать личность, мы можем создать тип `person`с полями "имя" и "возраст". Мы назовем этот тип `структурой(struct)`:
6-
7-
type person struct {
8-
name string
9-
age int
10-
}
11-
6+
```Go
7+
type person struct {
8+
name string
9+
age int
10+
}
11+
```
1212
Вот так как легко определять `структуру`!
1313

1414
У нас есть два поля:
@@ -17,196 +17,196 @@
1717
- `age` - `int`, используется для того, чтобы хранить возраст человека.
1818

1919
Давайте посмотрим, как это использовать:
20-
21-
type person struct {
22-
name string
23-
age int
24-
}
25-
26-
var P person // p - переменная типа person
27-
28-
P.name = "Astaxie" // присваиваем "Astaxie" полю 'name' переменной p
29-
P.age = 25 // присваиваем 25 полю 'age' переменной p
30-
fmt.Printf("Имя человека - %s\n", P.name) // получаем значение поля 'name' переменной p
31-
20+
```Go
21+
type person struct {
22+
name string
23+
age int
24+
}
25+
26+
var P person // p - переменная типа person
27+
28+
P.name = "Astaxie" // присваиваем "Astaxie" полю 'name' переменной p
29+
P.age = 25 // присваиваем 25 полю 'age' переменной p
30+
fmt.Printf("Имя человека - %s\n", P.name) // получаем значение поля 'name' переменной p
31+
```
3232
Есть еще три способа определить `struct`:
3333

3434
- Присвоить начальные значения по порядку:
35-
36-
P := person{"Tom", 25}
37-
35+
```Go
36+
P := person{"Tom", 25}
37+
```
3838
- Использовать формат `поле:значение`, чтобы задать начальные значения полей структуры, при этом можно не соблюдать порядок, в котором поля шли при описании структуры:
39-
40-
P := person{age:24, name:"Bob"}
41-
39+
```Go
40+
P := person{age: 24, name: "Bob"}
41+
```
4242
- Определить анонимную структуру, а затем задать ей значения:
43-
44-
P := struct{name string; age int}{"Amy",18}
45-
43+
```Go
44+
P := struct{name string; age int}{"Amy", 18}
45+
```
4646
Давайте рассмотрим конкретный пример:
47+
```Go
48+
package main
49+
import "fmt"
4750

48-
package main
49-
import "fmt"
51+
// Определяем новый тип
52+
type person struct {
53+
name string
54+
age int
55+
}
5056

51-
// Определяем новый тип
52-
type person struct {
53-
name string
54-
age int
55-
}
57+
// сравниваем возраст у двух людей, затем возвращаем возраст старшего из них и разницу в возрасте.
58+
// структуры передаются по значению
59+
func Older(p1, p2 person) (person, int) {
60+
if p1.age > p2.age {
61+
return p1, p1.age - p2.age
62+
}
63+
return p2, p2.age - p1.age
64+
}
5665

57-
// сравниваем возраст у двух людей, затем возвращаем возраст старшего из них и разницу в возрасте.
58-
// структуры передаются по значению
59-
func Older(p1, p2 person) (person, int) {
60-
if p1.age>p2.age {
61-
return p1, p1.age-p2.age
62-
}
63-
return p2, p2.age-p1.age
64-
}
66+
func main() {
67+
var tom person
6568

66-
func main() {
67-
var tom person
69+
// задаем первоначальные значения
70+
tom.name, tom.age = "Tom", 18
6871

69-
// задаем первоначальные значения
70-
tom.name, tom.age = "Tom", 18
72+
// задаем значения в формате "поле:значение"
73+
bob := person{age: 25, name: "Bob"}
7174

72-
// задаем значения в формате "поле:значение"
73-
bob := person{age:25, name:"Bob"}
75+
// задаем значения в порядке, указанном при определении структуры
76+
paul := person{"Paul", 43}
7477

75-
// задаем значения в порядке, указанном при определении структуры
76-
paul := person{"Paul", 43}
78+
tb_Older, tb_diff := Older(tom, bob)
79+
tp_Older, tp_diff := Older(tom, paul)
80+
bp_Older, bp_diff := Older(bob, paul)
7781

78-
tb_Older, tb_diff := Older(tom, bob)
79-
tp_Older, tp_diff := Older(tom, paul)
80-
bp_Older, bp_diff := Older(bob, paul)
82+
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, bob.name, tb_Older.name, tb_diff)
8183

82-
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, bob.name, tb_Older.name, tb_diff)
84+
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, paul.name, tp_Older.name, tp_diff)
8385

84-
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, paul.name, tp_Older.name, tp_diff)
85-
86-
fmt.Printf("Из %s и %s %s старше на %d лет\n", bob.name, paul.name, bp_Older.name, bp_diff)
87-
}
88-
86+
fmt.Printf("Из %s и %s %s старше на %d лет\n", bob.name, paul.name, bp_Older.name, bp_diff)
87+
}
88+
```
8989
### Встраиваемые поля в структуре
9090

9191
Я только что показал Вам, как определять структуру с именами и типами полей. Но Go поддерживает и поля с типами, но без имен. Мы называем это встраиваемыми полями.
9292

9393
Когда встраиваемое поле - структура, все поля этой структуры неявно становятся полями структуры, в которую оно встроено.
9494

9595
Посмотрим на пример:
96+
```Go
97+
package main
98+
import "fmt"
9699

97-
package main
98-
import "fmt"
99-
100-
type Human struct {
101-
name string
102-
age int
103-
weight int
104-
}
100+
type Human struct {
101+
name string
102+
age int
103+
weight int
104+
}
105105

106-
type Student struct {
106+
type Student struct {
107107
Human // встраиваемое поле; это означает, что структура Student включает в себя все поля структуры Human.
108108
specialty string
109-
}
110-
111-
func main() {
112-
// инициализируем студента
113-
mark := Student{Human{"Марк", 25, 120}, "Компьютерные науки"}
114-
115-
// получаем доступ к полям
116-
fmt.Println("Его имя: ", mark.name)
117-
fmt.Println("Его возраст: ", mark.age)
118-
fmt.Println("Его масса: ", mark.weight)
119-
fmt.Println("Его специализация: ", mark.specialty)
120-
// изменяем значения полей
121-
mark.specialty = "Искусственный интеллект"
122-
fmt.Println("Марк поменял специализацию")
123-
fmt.Println("Его специализация: ", mark.specialty)
124-
// изменяем возраст
125-
fmt.Println("Марк постарел")
126-
mark.age = 46
127-
fmt.Println("Его возраст: ", mark.age)
128-
// изменяем массу
129-
fmt.Println("Марк больше не атлет")
130-
mark.weight += 60
131-
fmt.Println("Его масса: ", mark.weight)
132-
}
133-
109+
}
110+
111+
func main() {
112+
// инициализируем студента
113+
mark := Student{Human{"Марк", 25, 120}, "Компьютерные науки"}
114+
115+
// получаем доступ к полям
116+
fmt.Println("Его имя: ", mark.name)
117+
fmt.Println("Его возраст: ", mark.age)
118+
fmt.Println("Его масса: ", mark.weight)
119+
fmt.Println("Его специализация: ", mark.specialty)
120+
// изменяем значения полей
121+
mark.specialty = "Искусственный интеллект"
122+
fmt.Println("Марк поменял специализацию")
123+
fmt.Println("Его специализация: ", mark.specialty)
124+
// изменяем возраст
125+
fmt.Println("Марк постарел")
126+
mark.age = 46
127+
fmt.Println("Его возраст: ", mark.age)
128+
// изменяем массу
129+
fmt.Println("Марк больше не атлет")
130+
mark.weight += 60
131+
fmt.Println("Его масса: ", mark.weight)
132+
}
133+
```
134134
![](images/2.4.student_struct.png?raw=true)
135135

136136
Рисунок 2.7 Наследование в Student и Human
137137

138138
Мы видим, что можно иметь доступ к значениям полей Student так же, как и к Human. Так работают встраиваемые поля. Очень круто, не так ли? Держитесь, есть кое-что покруче! Вы можете использовать Student, чтобы получить доступ к Human в этом встраиваемом поле!
139-
140-
mark.Human = Human{"Маркус", 55, 220}
141-
mark.Human.age -= 1
142-
143-
Все тиы данных в Go могут использованы в качестве встраиваемых полей:
144-
145-
package main
146-
import "fmt"
147-
148-
type Skills []string
149-
150-
type Human struct {
151-
name string
152-
age int
153-
weight int
154-
}
155-
156-
type Student struct {
157-
Human // struct как встраиваемое поле
158-
Skills // срез из строк как встраиваемое поле
159-
int // встроенный тип как встраиваемое поле
160-
specialty string
161-
}
162-
163-
func main() {
164-
// Инициализируем студента Джейн
165-
jane := Student{Human:Human{"Джейн", 35, 100}, specialty:"Биология"}
166-
// доступ к полям
167-
fmt.Println("Ее имя: ", jane.name)
168-
fmt.Println("Ее возраст: ", jane.age)
169-
fmt.Println("Ее масса: ", jane.weight)
170-
fmt.Println("Ее специализация: ", jane.specialty)
171-
// изменяем поле навыков
172-
jane.Skills = []string{"анатомия"}
173-
fmt.Println("Ее навыки: ", jane.Skills)
174-
fmt.Println("Она овладела еще двумя навыками: ")
175-
jane.Skills = append(jane.Skills, "физика", "golang")
176-
fmt.Println("Теперь ее навыки: ", jane.Skills)
177-
// изменяем встраиваемое поле
178-
jane.int = 3
179-
fmt.Println("Ее любимое число: ", jane.int)
180-
}
181-
139+
```Go
140+
mark.Human = Human{"Маркус", 55, 220}
141+
mark.Human.age -= 1
142+
```
143+
Все типы данных в Go могут быть использованы в качестве встраиваемых полей:
144+
```Go
145+
package main
146+
import "fmt"
147+
148+
type Skills []string
149+
150+
type Human struct {
151+
name string
152+
age int
153+
weight int
154+
}
155+
156+
type Student struct {
157+
Human // struct как встраиваемое поле
158+
Skills // срез из строк как встраиваемое поле
159+
int // встроенный тип как встраиваемое поле
160+
specialty string
161+
}
162+
163+
func main() {
164+
// Инициализируем студента Джейн
165+
jane := Student{Human:Human{"Джейн", 35, 100}, specialty:"Биология"}
166+
// доступ к полям
167+
fmt.Println("Ее имя: ", jane.name)
168+
fmt.Println("Ее возраст: ", jane.age)
169+
fmt.Println("Ее масса: ", jane.weight)
170+
fmt.Println("Ее специализация: ", jane.specialty)
171+
// изменяем поле навыков
172+
jane.Skills = []string{"анатомия"}
173+
fmt.Println("Ее навыки: ", jane.Skills)
174+
fmt.Println("Она овладела еще двумя навыками: ")
175+
jane.Skills = append(jane.Skills, "физика", "golang")
176+
fmt.Println("Теперь ее навыки: ", jane.Skills)
177+
// изменяем встраиваемое поле
178+
jane.int = 3
179+
fmt.Println("Ее любимое число: ", jane.int)
180+
}
181+
```
182182
В примере выше мы можем видеть, что данные всех типов могут быть встраиваемыми полями, и мы можем использовать функции, чтобы оперировать ими.
183183

184184
Есть, впрочем, одна проблема. Если у `Human` есть поле под названием `phone`, а у `Student` тоже есть поле с таким именем, как нам быть?
185185

186186
В Go есть простой способ решить эту задачу. Внешние поля имеют уровень доступа выше, что означает, что, обращаясь к `student.phone`, мы оперируем с полем `phone` в `student`,а не в `Human`. Это свойство проще представить как `перегрузку` полей.
187-
188-
package main
189-
import "fmt"
190-
191-
type Human struct {
192-
name string
193-
age int
194-
phone string // у Human есть поле phone
195-
}
196-
197-
type Employee struct {
198-
Human // встраиваемое поле Human
199-
specialty string
200-
phone string // у Employee также появляется поле phone
201-
}
202-
203-
func main() {
204-
Bob := Employee{Human{"Боб", 34, "777-444-XXXX"}, "Дизайнер", "333-222"}
205-
fmt.Println("Рабочий телефон Боба:", Bob.phone)
206-
// оперируем с поле phone в Human
207-
fmt.Println("Личный телефон Боба:", Bob.Human.phone)
208-
}
209-
187+
```Go
188+
package main
189+
import "fmt"
190+
191+
type Human struct {
192+
name string
193+
age int
194+
phone string // у Human есть поле phone
195+
}
196+
197+
type Employee struct {
198+
Human // встраиваемое поле Human
199+
specialty string
200+
phone string // у Employee также появляется поле phone
201+
}
202+
203+
func main() {
204+
Bob := Employee{Human{"Боб", 34, "777-444-XXXX"}, "Дизайнер", "333-222"}
205+
fmt.Println("Рабочий телефон Боба:", Bob.phone)
206+
// оперируем с поле phone в Human
207+
fmt.Println("Личный телефон Боба:", Bob.Human.phone)
208+
}
209+
```
210210
## Ссылки
211211

212212
- [Содержание](preface.md)

0 commit comments

Comments
 (0)