Golang: Структуры в срезах
В Go часто возникает необходимость хранить набор однотипных структур. Для этого удобно использовать срезы структур. Такой подход позволяет работать с коллекцией объектов, каждый из которых имеет одинаковый набор полей.
Объявление среза структур
Срез структур можно объявить так же, как и срез базовых типов:
type User struct {
Name string
Email string
}
func main() {
users := []User{
{Name: "Семен", Email: "semen@example.com"},
{Name: "Юля", Email: "yulia@example.com"},
}
for _, u := range users {
fmt.Println(u.Name, u.Email)
}
}
Добавление новых элементов
Элементы добавляются с помощью append
:
users = append(users, User{Name: "Алексей", Email: "alex@example.com"})
Изменение значений внутри среза
Так как срез хранит копии структур, при изменении элемента важно помнить о передаче по значению. Например:
users[0].Name = "Семен Иванов"
Изменение произойдет напрямую, так как мы работаем с элементом по индексу.
Срез указателей на структуры
Если нам нужно хранить и изменять объекты по ссылке, можно использовать срез указателей:
type User struct {
Name string
Email string
}
func main() {
users := []*User{
{Name: "Семен", Email: "semen@example.com"},
{Name: "Юля", Email: "yulia@example.com"},
}
users[0].Name = "Семен Иванов" // Изменение отразится на оригинальном объекте
}
Использование указателей полезно, если структуры большие и их копирование неэффективно.
Поиск и фильтрация
Для поиска элементов в срезе структур можно использовать обычные циклы:
func FindUserByEmail(users []User, email string) *User {
for i := range users {
if users[i].Email == email {
return &users[i]
}
}
return nil
}
Задание
Создайте функцию FindUserNames()
, которая принимает срез структур User
и возвращает срез имен всех пользователей, у которых email оканчивается на @example.com
.
-
Структура
User
уже объявлена:type User struct { Name string Email string }
-
Если пользователей с таким email нет, функция должна вернуть пустой срез (а не
nil
). -
Порядок имен в возвращаемом срезе должен соответствовать исходному порядку.
Пример
users := []User{
{Name: "Семен", Email: "semen@example.com"},
{Name: "Юля", Email: "yulia@gmail.com"},
{Name: "Алексей", Email: "alex@example.com"},
}
names := FindUserNames(users)
// Ожидаемый результат: []string{"Семен", "Алексей"}
Команда проекта находится в телеграм-сообществе. Там можно задать любой вопрос и повлиять на проект
Если вы зашли в тупик, то самое время поговорить с нашим асситентом Тота во вкладке "ИИ-помощник":
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи. В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в обратной связи нашего сообщества
Ваше упражнение проверяется по этим тестам
package solution
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFindUserNames(t *testing.T) {
users := []User{
{Name: "Семен", Email: "semen@example.com"},
{Name: "Юля", Email: "yulia@gmail.com"},
{Name: "Алексей", Email: "alex@example.com"},
}
expected := []string{"Семен", "Алексей"}
result := FindUserNames(users)
assert.Equal(t, expected, result, "Должны быть возвращены только пользователи с email @example.com")
}
func TestFindUserNamesEmpty(t *testing.T) {
users := []User{
{Name: "Юля", Email: "yulia@gmail.com"},
{Name: "Виктор", Email: "victor@mail.ru"},
}
expected := []string{}
result := FindUserNames(users)
assert.Equal(t, expected, result, "Если нет email с @example.com, должен вернуться пустой срез")
}
Решение учителя откроется через:
20:00
