Update 02.4.md

Подсветка синтаксиса и мелкие правки
This commit is contained in:
Bloom
2017-05-27 13:12:06 +07:00
committed by GitHub
parent aac6e2872f
commit bf39135259

View File

@@ -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)
} }
```
![](images/2.4.student_struct.png?raw=true) ![](images/2.4.student_struct.png?raw=true)
Рисунок 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)