Кусочек разрезов - программирование
Подтвердить что ты не робот

Кусочек разрезов

В настоящий момент я прохожу через отличный Tour of Go. Я закончил одно из упражнений (№ 45) со следующим решением:

func Pic(dx, dy int) [][]uint8 {
    pic := make([][]uint8, dy) /* type declaration */
    for i := range pic {
        pic[i] = make([]uint8, dx) /* again the type? */
        for j := range pic[i] {
            pic[i][j] = uint8((i+j)/2)
        }
    }
    return pic
}

Я не понимаю, почему я должен использовать инструкцию make с типом uint8 дважды (см. комментарии в фрагменте). Это кажется излишним, но я не могу понять, как это сделать другим способом.

4b9b3361

Ответ 1

В Go нет другого способа сделать это.

Да, я согласен, что это многословно, но необходимо. Второй оператор make() полностью не зависит от первого. Можно утверждать, что компилятор должен иметь возможность выводить тип из pic[i], но на данный момент этого не происходит.

Еще один момент: как выглядел бы оператор make(), если бы вы опустили тип во втором случае? Функция make() по-прежнему требуется для фактического распределения и для указания требуемой длины/емкости.

Как побочная заметка, вы перепутали длины срезов. Упражнение утверждает, что срез верхнего уровня должен иметь длину dy, а не dx по мере ввода кода.

Ответ 2

Чтобы быть явным, мы можем использовать круглые скобки для перезаписи [][]uint8 как []([]uint8): срез (фрагменты типа uint8).

Используя сделать встроенную функцию, для фрагмента типа T, make(T, n) возвращает фрагмент типа T с длиной n и емкость n.

Следовательно, make([][]uint8, 2) эквивалентен make([]([]uint8), 2), он возвращает срез с длиной и емкостью 2 фрагментов типа uint8, где каждый фрагмент типа uint8 инициализируется до нуля значение (a nil ссылка с длиной и емкостью нуля).

Многомерные срезы зубчатые и аналогичны многомерным зубчатым массивам.

Например,

package main

import "fmt"

func main() {
    ss := make([][]uint8, 2) // ss is []([]uint8)
    fmt.Printf("ss:    %T %v %d\n", ss, ss, len(ss))
    for i, s := range ss { // s is []uint8
        fmt.Printf("ss[%d]: %T %v %d\n", i, s, s, len(s))
    }
}

Вывод:

ss:    [][]uint8 [[] []] 2
ss[0]: []uint8 [] 0
ss[1]: []uint8 [] 0