From bf39135259ee40d9b7c4a5b9a0f51ad67ae71d4b Mon Sep 17 00:00:00 2001 From: Bloom Date: Sat, 27 May 2017 13:12:06 +0700 Subject: [PATCH] Update 02.4.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Подсветка синтаксиса и мелкие правки --- ru/02.4.md | 296 ++++++++++++++++++++++++++--------------------------- 1 file changed, 148 insertions(+), 148 deletions(-) diff --git a/ru/02.4.md b/ru/02.4.md index 0f53b30d..5a94f1f0 100644 --- a/ru/02.4.md +++ b/ru/02.4.md @@ -3,12 +3,12 @@ ## struct В Go мы можем определять новые типы контейнеров свойств или полей так же, как и в других языках программирования. Например, чтобы описать личность, мы можем создать тип `person`с полями "имя" и "возраст". Мы назовем этот тип `структурой(struct)`: - - type person struct { - name string - age int - } - +```Go +type person struct { + name string + age int +} +``` Вот так как легко определять `структуру`! У нас есть два поля: @@ -17,75 +17,75 @@ - `age` - `int`, используется для того, чтобы хранить возраст человека. Давайте посмотрим, как это использовать: +```Go +type person struct { + name string + age int +} - type person struct { - 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 +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 +``` Есть еще три способа определить `struct`: - Присвоить начальные значения по порядку: - - P := person{"Tom", 25} - +```Go +P := person{"Tom", 25} +``` - Использовать формат `поле:значение`, чтобы задать начальные значения полей структуры, при этом можно не соблюдать порядок, в котором поля шли при описании структуры: - - P := person{age:24, name:"Bob"} - +```Go +P := person{age: 24, name: "Bob"} +``` - Определить анонимную структуру, а затем задать ей значения: - - P := struct{name string; age int}{"Amy",18} - +```Go +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 - age int - } +// сравниваем возраст у двух людей, затем возвращаем возраст старшего из них и разницу в возрасте. +// структуры передаются по значению +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 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 - 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} - // задаем значения в порядке, указанном при определении структуры - 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) - tb_Older, tb_diff := Older(tom, bob) - 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, 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 поддерживает и поля с типами, но без имен. Мы называем это встраиваемыми полями. @@ -93,120 +93,120 @@ Когда встраиваемое поле - структура, все поля этой структуры неявно становятся полями структуры, в которую оно встроено. Посмотрим на пример: +```Go +package main +import "fmt" - package main - import "fmt" +type Human struct { + name string + age int + weight int +} - type Human struct { - name string - age int - weight int - } - - type Student struct { +type Student struct { Human // встраиваемое поле; это означает, что структура Student включает в себя все поля структуры Human. specialty string - } +} - func main() { - // инициализируем студента - mark := Student{Human{"Марк", 25, 120}, "Компьютерные науки"} +func main() { + // инициализируем студента + mark := Student{Human{"Марк", 25, 120}, "Компьютерные науки"} - // получаем доступ к полям - fmt.Println("Его имя: ", mark.name) - fmt.Println("Его возраст: ", mark.age) - fmt.Println("Его масса: ", mark.weight) - fmt.Println("Его специализация: ", mark.specialty) - // изменяем значения полей - mark.specialty = "Искусственный интеллект" - fmt.Println("Марк поменял специализацию") - fmt.Println("Его специализация: ", mark.specialty) - // изменяем возраст - fmt.Println("Марк постарел") - mark.age = 46 - fmt.Println("Его возраст: ", mark.age) - // изменяем массу - fmt.Println("Марк больше не атлет") - mark.weight += 60 - fmt.Println("Его масса: ", mark.weight) - } - + // получаем доступ к полям + fmt.Println("Его имя: ", mark.name) + fmt.Println("Его возраст: ", mark.age) + fmt.Println("Его масса: ", mark.weight) + fmt.Println("Его специализация: ", mark.specialty) + // изменяем значения полей + mark.specialty = "Искусственный интеллект" + fmt.Println("Марк поменял специализацию") + fmt.Println("Его специализация: ", mark.specialty) + // изменяем возраст + fmt.Println("Марк постарел") + mark.age = 46 + fmt.Println("Его возраст: ", mark.age) + // изменяем массу + fmt.Println("Марк больше не атлет") + mark.weight += 60 + fmt.Println("Его масса: ", mark.weight) +} +``` ![](images/2.4.student_struct.png?raw=true) Рисунок 2.7 Наследование в 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} - mark.Human.age -= 1 - -Все тиы данных в Go могут использованы в качестве встраиваемых полей: +type Skills []string - package main - import "fmt" +type Human struct { + name string + age int + weight int +} - type Skills []string +type Student struct { + Human // struct как встраиваемое поле + Skills // срез из строк как встраиваемое поле + int // встроенный тип как встраиваемое поле + specialty string +} - type Human struct { - name string - age int - weight int - } - - type Student struct { - Human // struct как встраиваемое поле - Skills // срез из строк как встраиваемое поле - int // встроенный тип как встраиваемое поле - specialty string - } - - func main() { - // Инициализируем студента Джейн - jane := Student{Human:Human{"Джейн", 35, 100}, specialty:"Биология"} - // доступ к полям - 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) - } - +func main() { + // Инициализируем студента Джейн + jane := Student{Human:Human{"Джейн", 35, 100}, specialty:"Биология"} + // доступ к полям + 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` тоже есть поле с таким именем, как нам быть? В Go есть простой способ решить эту задачу. Внешние поля имеют уровень доступа выше, что означает, что, обращаясь к `student.phone`, мы оперируем с полем `phone` в `student`,а не в `Human`. Это свойство проще представить как `перегрузку` полей. +```Go +package main +import "fmt" - package main - import "fmt" +type Human struct { + name string + age int + phone string // у Human есть поле phone +} - type Human struct { - name string - age int - phone string // у Human есть поле phone - } +type Employee struct { + Human // встраиваемое поле Human + specialty string + phone string // у Employee также появляется поле phone +} - type Employee struct { - Human // встраиваемое поле Human - specialty string - phone string // у Employee также появляется поле phone - } - - func main() { - Bob := Employee{Human{"Боб", 34, "777-444-XXXX"}, "Дизайнер", "333-222"} - fmt.Println("Рабочий телефон Боба:", Bob.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)