Go имеет struct
s вместо class
es, как мы видим в других языках. Структуры в основном охватывают некоторые поля внутри.
package main import ( "fmt" ) type School struct { Name string Country string NumOfStudents int } func main() { school := School{"ABC Primary School", "Canada", 5000} fmt.Println(school.Name) }
Выше у нас есть school
как структура, которая содержит Name
, Address
и NumOfStudents
.
Чтобы получить доступ к любому из полей в структуре, мы используем оператор .
, например. school.Name
.
Мы можем инициализировать struct
несколькими способами.
func main() { // initializing according to the order of fields without specifying field names school := School{"ABC Primary School", "Canada", 5000} fmt.Println(school.Name) // initializing with field names and in random order school2 := School{Name: "XYZ Primary School", NumOfStudents: 2000, Country: "America"} fmt.Println(school2.NumOfStudents) // initializing only some struct fields school3 := School{Name:"Jingle Bells Secondary School"} fmt.Println(school3.Name) }
Приведенное выше выведет следующее:
ABC Primary School 2000 Jingle Bells Secondary School
Примечание
Название полей в структуре, начинающееся с заглавных букв, позволяет нам свободно обращаться к ним. Читайте дальше, чтобы узнать, как ограничить доступ.
Анонимные члены структуры
В некотором смысле наследование может осуществляться с использованием анонимных членов структуры.
type Lab struct { numOfEquipment int } type School struct { Lab //anonymous field numOfStudents int } func main() { // initialise a school with 300 students and a lab with 10 equipment school := School{Lab{10}, 300} fmt.Println(school.numOfEquipment) }
Мы достигаем наследования через композицию. Это означает, что school.numOfEquipment
является допустимым доступом, хотя School
не содержит этого поля напрямую.
Если две структуры, из которых вы «вставляете», имеют одинаковое имя свойства, нам нужно указать «промежуточный» тип структуры, а затем имя свойства.
type Lab struct { numOfEquipment int } type SportsRoom struct { numOfEquipment int } type School struct { Lab SportsRoom } func main() { school := School{Lab{3}, SportsRoom{4} } fmt.Println(school.Lab.numOfEquipment + school.SportsRoom.numOfEquipment) }
Методы структур
У нас могут быть приемники указателей для структур, т.е. тип получателя имеет синтаксис *T
, где T
— тип структуры.
package main import ( "fmt" ) type Circle struct { radius int } // pointer receiver method func increaseRadiusByOne(c *Circle) { c.radius += 1 } // value receiver method func increaseRadiusByTwo(c Circle) { c.radius += 2 } func main() { c := Circle{2} increaseRadiusByOne(&c) // passing the reference to c fmt.Println(c.radius) // prints 3 increaseRadiusByTwo(c) // passing a copy of c fmt.Println(c.radius) // still prints 3 }
Использование получателя указателя изменит исходную структуру, поскольку она получает ссылку на сам фактический объект. В приведенном выше примере increaseRadiusByOne(&c)
передает фактический объект c
, определенный в методе main
. Таким образом, фактический радиус изменяется.
При использовании получателя значения получается копия структуры. При изменении свойств структуры в нем не будет никаких изменений в исходной структуре. В приведенном выше примере increaseRadiusByTwo(c)
передает копию c
, и изменение копии c
не влияет на фактический c
, определенный в методе main
.Первоначально опубликовано на https://rightfrombasics.com 29 декабря 2018 г.
Первоначально опубликовано на https://rightfrombasics.com 29 декабря 2018 г.