На практике не часто сталкиваешься с массивами из-за ограниченной длины при строгой типизации. Вместо этого повсеместно используются слайсы. Слайс — это массив неопределенной длины (или динамический массив):
var nums = []int{1,2,3}
nums := []int{1,2,3}
Чтение и запись осуществляется точно так же как в массивах:
nums := []int{1,2,3}
nums[2] // 3
nums[0] = 10 // [10, 2, 3]
nums[:2] // [10, 2]
В слайсы можно добавлять элементы с помощью встроенной функции func append(slice []Type, elems ...Type) []Type
, которая возвращает новый слайс с добавленным элементом:
words := []string{"hello"}
words = append(words, "world") // ["hello", "world"]
Так как слайс имеет нефиксированную длину, "под капотом" лежит более сложная структура, чем у массива. Помимо самих значений слайс хранит 2 дополнительных свойства: длину массива len (длина) и cap (вместимость). Благодаря этому возможно инициализировать слайс нужной длины с помощью встроенной функции func make(t Type, len, cap IntegerType) Type
. Понимание, где лучше использовать какой способ инициализации, приходит с опытом, но для старта рекомендуется использовать make
везде, где можно:
// len = 5. Массив сразу будет заполнен 5-ю нулевыми значениями
nums := make([]int, 5, 5) // [0, 0, 0, 0, 0]
// len = 0, но cap = 5. Массив будет пустым, однако заполнение слайса через append будет эффективным, потому что в памяти уже выделен массив нужной длины
nums := make([]int, 0, 5) // []
Передача слайса как аргумента функции происходит хитро. Длина и вместимость передаются по значению, но массив значений передается по ссылке. Вследствие этого получается неявное поведение: добавленные элементы не сохранятся в исходный слайс, но изменение существующих останется:
package main
import (
"fmt"
)
func main() {
nums := []int{1, 2, 3, 4, 5}
modifySlice(nums)
fmt.Println(nums) // [1 2 10 4 5]
}
func modifySlice(nums []int) {
nums[2] = 10 // элемент будет и в исходном слайсе
nums = append(nums, 6) // элемент не добавится в исходный слайс
}
Реализуйте функцию RemoveFirstElement(slice []int) []int
, которая оторая удаляет первый элемент из слайса. Если в функцию передан пустой слайс, то функция также вернет пустой слайс.
original := []int{1, 2, 3, 4, 5}
RemoveFirstElement(original) // [2 3 4 5]
RemoveFirstElement([]int{}) // []
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1package solution
2
3import (
4 "testing"
5
6 "github.com/stretchr/testify/assert"
7)
8
9func TestRemoveFirstElement(t *testing.T) {
10 a := assert.New(t)
11 a.Equal([]int{2, 3, 4}, RemoveFirstElement([]int{1, 2, 3, 4}))
12 a.Equal([]int{}, RemoveFirstElement([]int{}))
13 a.Equal([]int{-3, -2}, RemoveFirstElement([]int{-4, -3, -2}))
14 a.Equal([]int{}, RemoveFirstElement([]int{3}))
15}
16
Решение учителя откроется через: