Update 02.4.md
Подсветка синтаксиса и мелкие правки
This commit is contained in:
296
ru/02.4.md
296
ru/02.4.md
@@ -3,12 +3,12 @@
|
|||||||
## struct
|
## struct
|
||||||
|
|
||||||
В Go мы можем определять новые типы контейнеров свойств или полей так же, как и в других языках программирования. Например, чтобы описать личность, мы можем создать тип `person`с полями "имя" и "возраст". Мы назовем этот тип `структурой(struct)`:
|
В Go мы можем определять новые типы контейнеров свойств или полей так же, как и в других языках программирования. Например, чтобы описать личность, мы можем создать тип `person`с полями "имя" и "возраст". Мы назовем этот тип `структурой(struct)`:
|
||||||
|
```Go
|
||||||
type person struct {
|
type person struct {
|
||||||
name string
|
name string
|
||||||
age int
|
age int
|
||||||
}
|
}
|
||||||
|
```
|
||||||
Вот так как легко определять `структуру`!
|
Вот так как легко определять `структуру`!
|
||||||
|
|
||||||
У нас есть два поля:
|
У нас есть два поля:
|
||||||
@@ -17,75 +17,75 @@
|
|||||||
- `age` - `int`, используется для того, чтобы хранить возраст человека.
|
- `age` - `int`, используется для того, чтобы хранить возраст человека.
|
||||||
|
|
||||||
Давайте посмотрим, как это использовать:
|
Давайте посмотрим, как это использовать:
|
||||||
|
```Go
|
||||||
|
type person struct {
|
||||||
|
name string
|
||||||
|
age int
|
||||||
|
}
|
||||||
|
|
||||||
type person struct {
|
var P person // p - переменная типа person
|
||||||
name string
|
|
||||||
age int
|
|
||||||
}
|
|
||||||
|
|
||||||
var P person // p - переменная типа person
|
|
||||||
|
|
||||||
P.name = "Astaxie" // присваиваем "Astaxie" полю 'name' переменной p
|
|
||||||
P.age = 25 // присваиваем 25 полю 'age' переменной p
|
|
||||||
fmt.Printf("Имя человека - %s\n", P.name) // получаем значение поля 'name' переменной p
|
|
||||||
|
|
||||||
|
P.name = "Astaxie" // присваиваем "Astaxie" полю 'name' переменной p
|
||||||
|
P.age = 25 // присваиваем 25 полю 'age' переменной p
|
||||||
|
fmt.Printf("Имя человека - %s\n", P.name) // получаем значение поля 'name' переменной p
|
||||||
|
```
|
||||||
Есть еще три способа определить `struct`:
|
Есть еще три способа определить `struct`:
|
||||||
|
|
||||||
- Присвоить начальные значения по порядку:
|
- Присвоить начальные значения по порядку:
|
||||||
|
```Go
|
||||||
P := person{"Tom", 25}
|
P := person{"Tom", 25}
|
||||||
|
```
|
||||||
- Использовать формат `поле:значение`, чтобы задать начальные значения полей структуры, при этом можно не соблюдать порядок, в котором поля шли при описании структуры:
|
- Использовать формат `поле:значение`, чтобы задать начальные значения полей структуры, при этом можно не соблюдать порядок, в котором поля шли при описании структуры:
|
||||||
|
```Go
|
||||||
P := person{age:24, name:"Bob"}
|
P := person{age: 24, name: "Bob"}
|
||||||
|
```
|
||||||
- Определить анонимную структуру, а затем задать ей значения:
|
- Определить анонимную структуру, а затем задать ей значения:
|
||||||
|
```Go
|
||||||
P := struct{name string; age int}{"Amy",18}
|
P := struct{name string; age int}{"Amy", 18}
|
||||||
|
```
|
||||||
Давайте рассмотрим конкретный пример:
|
Давайте рассмотрим конкретный пример:
|
||||||
|
```Go
|
||||||
|
package main
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
package main
|
// Определяем новый тип
|
||||||
import "fmt"
|
type person struct {
|
||||||
|
name string
|
||||||
|
age int
|
||||||
|
}
|
||||||
|
|
||||||
// Определяем новый тип
|
// сравниваем возраст у двух людей, затем возвращаем возраст старшего из них и разницу в возрасте.
|
||||||
type person struct {
|
// структуры передаются по значению
|
||||||
name string
|
func Older(p1, p2 person) (person, int) {
|
||||||
age int
|
if p1.age > p2.age {
|
||||||
}
|
return p1, p1.age - p2.age
|
||||||
|
}
|
||||||
|
return p2, p2.age - p1.age
|
||||||
|
}
|
||||||
|
|
||||||
// сравниваем возраст у двух людей, затем возвращаем возраст старшего из них и разницу в возрасте.
|
func main() {
|
||||||
// структуры передаются по значению
|
var tom person
|
||||||
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
|
tom.name, tom.age = "Tom", 18
|
||||||
|
|
||||||
// задаем первоначальные значения
|
// задаем значения в формате "поле:значение"
|
||||||
tom.name, tom.age = "Tom", 18
|
bob := person{age: 25, name: "Bob"}
|
||||||
|
|
||||||
// задаем значения в формате "поле:значение"
|
// задаем значения в порядке, указанном при определении структуры
|
||||||
bob := person{age:25, name:"Bob"}
|
paul := person{"Paul", 43}
|
||||||
|
|
||||||
// задаем значения в порядке, указанном при определении структуры
|
tb_Older, tb_diff := Older(tom, bob)
|
||||||
paul := person{"Paul", 43}
|
tp_Older, tp_diff := Older(tom, paul)
|
||||||
|
bp_Older, bp_diff := Older(bob, paul)
|
||||||
|
|
||||||
tb_Older, tb_diff := Older(tom, bob)
|
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, bob.name, tb_Older.name, tb_diff)
|
||||||
tp_Older, tp_diff := Older(tom, paul)
|
|
||||||
bp_Older, bp_diff := Older(bob, paul)
|
|
||||||
|
|
||||||
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, bob.name, tb_Older.name, tb_diff)
|
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, paul.name, tp_Older.name, tp_diff)
|
||||||
|
|
||||||
fmt.Printf("Из %s и %s %s старше на %d лет\n", tom.name, paul.name, tp_Older.name, tp_diff)
|
fmt.Printf("Из %s и %s %s старше на %d лет\n", bob.name, paul.name, bp_Older.name, bp_diff)
|
||||||
|
}
|
||||||
fmt.Printf("Из %s и %s %s старше на %d лет\n", bob.name, paul.name, bp_Older.name, bp_diff)
|
```
|
||||||
}
|
|
||||||
|
|
||||||
### Встраиваемые поля в структуре
|
### Встраиваемые поля в структуре
|
||||||
|
|
||||||
Я только что показал Вам, как определять структуру с именами и типами полей. Но Go поддерживает и поля с типами, но без имен. Мы называем это встраиваемыми полями.
|
Я только что показал Вам, как определять структуру с именами и типами полей. Но Go поддерживает и поля с типами, но без имен. Мы называем это встраиваемыми полями.
|
||||||
@@ -93,120 +93,120 @@
|
|||||||
Когда встраиваемое поле - структура, все поля этой структуры неявно становятся полями структуры, в которую оно встроено.
|
Когда встраиваемое поле - структура, все поля этой структуры неявно становятся полями структуры, в которую оно встроено.
|
||||||
|
|
||||||
Посмотрим на пример:
|
Посмотрим на пример:
|
||||||
|
```Go
|
||||||
|
package main
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
package main
|
type Human struct {
|
||||||
import "fmt"
|
name string
|
||||||
|
age int
|
||||||
|
weight int
|
||||||
|
}
|
||||||
|
|
||||||
type Human struct {
|
type Student struct {
|
||||||
name string
|
|
||||||
age int
|
|
||||||
weight int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Student struct {
|
|
||||||
Human // встраиваемое поле; это означает, что структура Student включает в себя все поля структуры Human.
|
Human // встраиваемое поле; это означает, что структура Student включает в себя все поля структуры Human.
|
||||||
specialty string
|
specialty string
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// инициализируем студента
|
// инициализируем студента
|
||||||
mark := Student{Human{"Марк", 25, 120}, "Компьютерные науки"}
|
mark := Student{Human{"Марк", 25, 120}, "Компьютерные науки"}
|
||||||
|
|
||||||
// получаем доступ к полям
|
// получаем доступ к полям
|
||||||
fmt.Println("Его имя: ", mark.name)
|
fmt.Println("Его имя: ", mark.name)
|
||||||
fmt.Println("Его возраст: ", mark.age)
|
fmt.Println("Его возраст: ", mark.age)
|
||||||
fmt.Println("Его масса: ", mark.weight)
|
fmt.Println("Его масса: ", mark.weight)
|
||||||
fmt.Println("Его специализация: ", mark.specialty)
|
fmt.Println("Его специализация: ", mark.specialty)
|
||||||
// изменяем значения полей
|
// изменяем значения полей
|
||||||
mark.specialty = "Искусственный интеллект"
|
mark.specialty = "Искусственный интеллект"
|
||||||
fmt.Println("Марк поменял специализацию")
|
fmt.Println("Марк поменял специализацию")
|
||||||
fmt.Println("Его специализация: ", mark.specialty)
|
fmt.Println("Его специализация: ", mark.specialty)
|
||||||
// изменяем возраст
|
// изменяем возраст
|
||||||
fmt.Println("Марк постарел")
|
fmt.Println("Марк постарел")
|
||||||
mark.age = 46
|
mark.age = 46
|
||||||
fmt.Println("Его возраст: ", mark.age)
|
fmt.Println("Его возраст: ", mark.age)
|
||||||
// изменяем массу
|
// изменяем массу
|
||||||
fmt.Println("Марк больше не атлет")
|
fmt.Println("Марк больше не атлет")
|
||||||
mark.weight += 60
|
mark.weight += 60
|
||||||
fmt.Println("Его масса: ", mark.weight)
|
fmt.Println("Его масса: ", mark.weight)
|
||||||
}
|
}
|
||||||
|
```
|
||||||

|

|
||||||
|
|
||||||
Рисунок 2.7 Наследование в Student и Human
|
Рисунок 2.7 Наследование в Student и Human
|
||||||
|
|
||||||
Мы видим, что можно иметь доступ к значениям полей Student так же, как и к Human. Так работают встраиваемые поля. Очень круто, не так ли? Держитесь, есть кое-что покруче! Вы можете использовать Student, чтобы получить доступ к Human в этом встраиваемом поле!
|
Мы видим, что можно иметь доступ к значениям полей Student так же, как и к Human. Так работают встраиваемые поля. Очень круто, не так ли? Держитесь, есть кое-что покруче! Вы можете использовать Student, чтобы получить доступ к Human в этом встраиваемом поле!
|
||||||
|
```Go
|
||||||
|
mark.Human = Human{"Маркус", 55, 220}
|
||||||
|
mark.Human.age -= 1
|
||||||
|
```
|
||||||
|
Все типы данных в Go могут быть использованы в качестве встраиваемых полей:
|
||||||
|
```Go
|
||||||
|
package main
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
mark.Human = Human{"Маркус", 55, 220}
|
type Skills []string
|
||||||
mark.Human.age -= 1
|
|
||||||
|
|
||||||
Все тиы данных в Go могут использованы в качестве встраиваемых полей:
|
|
||||||
|
|
||||||
package main
|
type Human struct {
|
||||||
import "fmt"
|
name string
|
||||||
|
age int
|
||||||
|
weight int
|
||||||
|
}
|
||||||
|
|
||||||
type Skills []string
|
type Student struct {
|
||||||
|
Human // struct как встраиваемое поле
|
||||||
|
Skills // срез из строк как встраиваемое поле
|
||||||
|
int // встроенный тип как встраиваемое поле
|
||||||
|
specialty string
|
||||||
|
}
|
||||||
|
|
||||||
type Human struct {
|
func main() {
|
||||||
name string
|
// Инициализируем студента Джейн
|
||||||
age int
|
jane := Student{Human:Human{"Джейн", 35, 100}, specialty:"Биология"}
|
||||||
weight int
|
// доступ к полям
|
||||||
}
|
fmt.Println("Ее имя: ", jane.name)
|
||||||
|
fmt.Println("Ее возраст: ", jane.age)
|
||||||
type Student struct {
|
fmt.Println("Ее масса: ", jane.weight)
|
||||||
Human // struct как встраиваемое поле
|
fmt.Println("Ее специализация: ", jane.specialty)
|
||||||
Skills // срез из строк как встраиваемое поле
|
// изменяем поле навыков
|
||||||
int // встроенный тип как встраиваемое поле
|
jane.Skills = []string{"анатомия"}
|
||||||
specialty string
|
fmt.Println("Ее навыки: ", jane.Skills)
|
||||||
}
|
fmt.Println("Она овладела еще двумя навыками: ")
|
||||||
|
jane.Skills = append(jane.Skills, "физика", "golang")
|
||||||
func main() {
|
fmt.Println("Теперь ее навыки: ", jane.Skills)
|
||||||
// Инициализируем студента Джейн
|
// изменяем встраиваемое поле
|
||||||
jane := Student{Human:Human{"Джейн", 35, 100}, specialty:"Биология"}
|
jane.int = 3
|
||||||
// доступ к полям
|
fmt.Println("Ее любимое число: ", jane.int)
|
||||||
fmt.Println("Ее имя: ", jane.name)
|
}
|
||||||
fmt.Println("Ее возраст: ", jane.age)
|
```
|
||||||
fmt.Println("Ее масса: ", jane.weight)
|
|
||||||
fmt.Println("Ее специализация: ", jane.specialty)
|
|
||||||
// изменяем поле навыков
|
|
||||||
jane.Skills = []string{"анатомия"}
|
|
||||||
fmt.Println("Ее навыки: ", jane.Skills)
|
|
||||||
fmt.Println("Она овладела еще двумя навыками: ")
|
|
||||||
jane.Skills = append(jane.Skills, "физика", "golang")
|
|
||||||
fmt.Println("Теперь ее навыки: ", jane.Skills)
|
|
||||||
// изменяем встраиваемое поле
|
|
||||||
jane.int = 3
|
|
||||||
fmt.Println("Ее любимое число: ", jane.int)
|
|
||||||
}
|
|
||||||
|
|
||||||
В примере выше мы можем видеть, что данные всех типов могут быть встраиваемыми полями, и мы можем использовать функции, чтобы оперировать ими.
|
В примере выше мы можем видеть, что данные всех типов могут быть встраиваемыми полями, и мы можем использовать функции, чтобы оперировать ими.
|
||||||
|
|
||||||
Есть, впрочем, одна проблема. Если у `Human` есть поле под названием `phone`, а у `Student` тоже есть поле с таким именем, как нам быть?
|
Есть, впрочем, одна проблема. Если у `Human` есть поле под названием `phone`, а у `Student` тоже есть поле с таким именем, как нам быть?
|
||||||
|
|
||||||
В Go есть простой способ решить эту задачу. Внешние поля имеют уровень доступа выше, что означает, что, обращаясь к `student.phone`, мы оперируем с полем `phone` в `student`,а не в `Human`. Это свойство проще представить как `перегрузку` полей.
|
В Go есть простой способ решить эту задачу. Внешние поля имеют уровень доступа выше, что означает, что, обращаясь к `student.phone`, мы оперируем с полем `phone` в `student`,а не в `Human`. Это свойство проще представить как `перегрузку` полей.
|
||||||
|
```Go
|
||||||
|
package main
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
package main
|
type Human struct {
|
||||||
import "fmt"
|
name string
|
||||||
|
age int
|
||||||
|
phone string // у Human есть поле phone
|
||||||
|
}
|
||||||
|
|
||||||
type Human struct {
|
type Employee struct {
|
||||||
name string
|
Human // встраиваемое поле Human
|
||||||
age int
|
specialty string
|
||||||
phone string // у Human есть поле phone
|
phone string // у Employee также появляется поле phone
|
||||||
}
|
}
|
||||||
|
|
||||||
type Employee struct {
|
func main() {
|
||||||
Human // встраиваемое поле Human
|
Bob := Employee{Human{"Боб", 34, "777-444-XXXX"}, "Дизайнер", "333-222"}
|
||||||
specialty string
|
fmt.Println("Рабочий телефон Боба:", Bob.phone)
|
||||||
phone string // у Employee также появляется поле phone
|
// оперируем с поле phone в Human
|
||||||
}
|
fmt.Println("Личный телефон Боба:", Bob.Human.phone)
|
||||||
|
}
|
||||||
func main() {
|
```
|
||||||
Bob := Employee{Human{"Боб", 34, "777-444-XXXX"}, "Дизайнер", "333-222"}
|
|
||||||
fmt.Println("Рабочий телефон Боба:", Bob.phone)
|
|
||||||
// оперируем с поле phone в Human
|
|
||||||
fmt.Println("Личный телефон Боба:", Bob.Human.phone)
|
|
||||||
}
|
|
||||||
|
|
||||||
## Ссылки
|
## Ссылки
|
||||||
|
|
||||||
- [Содержание](preface.md)
|
- [Содержание](preface.md)
|
||||||
|
|||||||
Reference in New Issue
Block a user