Давайте посмотрим на лес сначала, прежде чем смотреть на деревья.
Здесь есть много информативных ответов с большими подробностями, я не буду повторять ни одного из них. Ключ к программированию в JavaScript имеет сначала правильную ментальную модель общего исполнения.
Хорошие новости заключается в том, что, если вы хорошо понимаете этот момент, вам никогда не придется беспокоиться о гоночных условиях. Прежде всего вы должны понимать, как вы хотите упорядочить свой код как по существу ответ на разные дискретные события, и как вы хотите объединить их в логическую последовательность. Вы можете использовать обещания или новые асинхронные / ожидающие более высокие уровни в качестве инструментов для этой цели, или вы можете откатывать свои собственные.
Но вы не должны использовать какие-либо тактические инструменты для решения проблемы, пока вам не понравится актуальная проблемная область. Нарисуйте карту этих зависимостей, чтобы знать, что нужно запускать, когда. Попытка ad-hoc подхода ко всем этим обратным вызовам просто не поможет вам.
Это полностью согласуется, и есть, конечно, другие способы сделать это (например, 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])
}
(этот код, очевидно, не справляется с некоторыми краевыми случаями, но вы получаете идею )
Если бы мы попытались написать эквивалентную функцию, используя инклюзивный инклюзионный срез, это было бы значительно сложнее.
Если кто-то может подумать больше, пожалуйста, не стесняйтесь отредактируйте этот ответ и добавьте их.
Спецификация языка программирования Go
Для строки, массива, указателя на массив или среза a первичное выражение
a[low : high]
создает подстроку или срез. Индексы low и high определяют, какие элементы операнда a появляются в результате. Результат имеет индексы начиная с
0
и длины, равнойhigh - low
.Для удобства любой из индексов можно опустить. Недостающий низкий индекс по умолчанию равен нулю; Отсутствует высокий индекс по умолчанию для длины разрезанного операнда
Для массивов или строк индексы находятся в диапазоне, если 0 & lt; = низкий & lt; = высокий & lt; = len (a), в противном случае они являются вне диапазона. Для срезов верхняя граница индекса - это колпачок емкости (а), а не длина. Постоянный индекс должен быть неотрицательным и быть представленным значением типа int; для массивов или постоянных строк постоянные индексы также должны находиться в зоне действия. Если оба индекса являются постоянными, они должны удовлетворять минимуму & lt; = высокий. Если индексы находятся вне допустимого диапазона во время выполнения, возникает паника во время выполнения.
blockquote>Для
q := p[m:n]
,q
представляет собой фрагментp
, начинающийся с индексаm
для длины элементовn-m
.