Это полностью согласуется, и есть, конечно, другие способы сделать это (например, Matlab использует массивы, первый индекс которых равен 1). Выбор действительно сводится к тому, какие свойства вы хотите. Как оказалось, использование 0-индексированных массивов, где slicing является инклюзивным-эксклюзивным (то есть срез от a до b включает элемент a и исключает элемент b) имеет некоторые действительно приятные свойства, и, следовательно, это очень распространенный выбор. Вот несколько преимуществ.
Преимущества 0-индексированных массивов и инклюзивно-эксклюзивных разрезов
(обратите внимание, что я использую терминологию, отличную от Go, поэтому я расскажу о массивах в том, что C или Java будут говорить о них. Массивы - это то, что Go вызывает срезы, а срезы - субмассивы (т. е. «срез от индекса 1 к индексу 4»))
arr
, arr[0:len(arr)]
является только arr
. Это очень полезно на практике. Например, если я назову n, _ := r.Read(arr)
(где n
- количество байтов, прочитанных в arr
), тогда я могу просто сделать arr[:n]
, чтобы получить срез arr
, соответствующий фактически записанным данным в arr
. arr[0:i]
, arr[i:j]
, arr[j:k]
, arr[k:len(arr)]
, эти срезы полностью покрывают arr
. Вы можете нередко находить разбиение массива на такие подрезки, как это, но оно имеет ряд связанных преимуществ. Например, рассмотрим следующий код для разбиения массива на основе неотрицательных целых чисел: func consecutiveSlices(ints []int) [][]int {
ret := make([][]int, 0)
i, j := 0, 1
for j < len(ints) {
if ints[j] != ints[j-1] + 1 {
ret = append(ret, ints[i:j])
i = j
}
}
ret = append(ret, ints[i:j])
}
(этот код, очевидно, не справляется с некоторыми краевыми случаями, но вы получаете идею )
Если бы мы попытались написать эквивалентную функцию, используя инклюзивный инклюзионный срез, это было бы значительно сложнее.
Если кто-то может подумать больше, пожалуйста, не стесняйтесь отредактируйте этот ответ и добавьте их.