2016-04-14 4 views
0

GO MASTERs! не могли бы вы посоветовать?Массивная крышка перезапись

  1. с make ([] int, len, cap), позволяет GO разрешить инициализацию массива одновременно с объявлением?

    myArray := make([]int, 3, 10){1,2,3}

  2. Я вижу колпачок (туАггау) изменилась равно Len (MyArray) в случае ниже. Что имеет фундаментальное значение?

<ex> myArray := make([]int, 3, 10) myArray = []int{1,2,3} fmt.Println("len:"len(myArray),", cap:",cap(myArray))

Len: 3, крышка: 3

Почему крышка (туАггау) составляет 3 вместо 10, как я декларации?

Я инициализировал отдельный элемент напрямую. И это работает, как я хотел

<ex> myArray := make([]int, 3, 10) myArray[0] = 1 myArray[1] = 2 myArray[2] = 3 fmt.Println("len:"len(myArray),", cap:",cap(myArray))

Len: 3, колпачок: 10

ответ

2

Я считаю, что вы получаете этот результат, потому что в первом примере вы объявляете кусочек с длина 3 и колпачок 10. Однако в следующем утверждении вы назначаете совершенно другой срез этой переменной. Поскольку срез, присвоенный вам, был объявлен/инициализирован с использованием синтаксиса «композитный-литерал», и он имеет только 3 элемента, то есть емкость, с которой она инициализируется. Во втором примере вы присваиваете значения каждому индексу среза, созданного с помощью make, сохраняя свойства длины и емкости.

Чтобы попытаться дать дополнительные пояснения, в C# или Java или C++ это будет выглядеть так:

List<string> myStrings = new List<string>(); 
myStrings.Add("A string"); 

myStrings = new List<string>(); 

Как вы могли предположить, после присвоения нового списка переменной myStrings старый список будет потерян. Поэтому, чтобы дать простой ответ, вы не просто перезаписываете кепку, вы переписываете весь фрагмент. Значение, которое у вас есть в присваивании, которое перезаписывает его, вызывает создание среза с кепкой из 3, поэтому вы получаете этот результат.

+0

Я бы сказал, что вы объявляете только ломтик междунар и выделить экземпляр с длиной 3 и колпачком 10. Вы может объявлять и создавать экземпляры в одном выражении из-за короткой формы объявления. – Uvelichitel

+0

Спасибо Uvelichitel, но не ясно, если вы имели в виду, что я могу сделать экземпляр даже с make? Второй способ, который [] int {***} может достичь, но если «make()» может сделать или нет, это мой вопрос. – GoGo

+0

Да, я не уверен, что @Uvelichitel пытается передать. Оператор 'make' выделяет срез длиной 3, емкость 10.« x: = [] int {1,2,3} »называется« составным литералом », и, как и при создании механики, поскольку нет возможности (нет, где поставить эту информацию), емкость по умолчанию равна длине (это работает одинаково, когда вы вызываете make, опускающий третий аргумент). – evanmcdonnal

2

Так что здесь есть несколько вещей. Я бы настоятельно рекомендовал объяснение goblog: https://blog.golang.org/slices (перейдите к разделу с надписью Capacity). Кроме того, просто (крошечный) бит семантики, но это на самом деле кусочки, а не массивы :)

Чтобы понять, когда вы впервые объявили свой кусочек, у вас была длина 3 и емкость 10. Нет проблем с этим. Но затем вы обновите myArray и установите его как [] int {1,2,3}. Там нет проблем, это действительно так.

Проблема возникает, когда вы ожидали, что ваша предыдущая len/cap останется прежней; ваш фрагмент - это просто указатель на некоторое пространство в памяти. Итак, теперь вы изменили свой основной указатель (см. Goblog). Объем и длина среза теперь также изменены (по умолчанию - снова, см. Goblog).Вы можете увидеть то же изменение лена/колпачка, если бы вы добавить больше элементов:

myArray := make([]int, 3, 10) 
fmt.Println("len:"len(myArray),", cap:",cap(myArray)) // len: 3 cap: 10 

myArray := []int{1, 2, 3} 
fmt.Println("len:", len(myArray), "cap:", cap(myArray)) // len: 3 cap: 3 

myArray = append(myArray, 4) 
fmt.Println("len:", len(myArray), "cap:", cap(myArray)) // len: 4 cap: 8; automatically increases the cap 
+0

Спасибо william за хороший комментарий и блог! Итак, кажется, я создал два среза (с len, cap), а myArray перенаправил на более поздний, пока я ожидал, что первый останется. И встроенная функция (Append) будет выполнять либо reslice, если mothership (array) имеет достаточное количество выделенной памяти, либо регенерирует массив и срез, если исходный срез превышает емкость. Пожалуйста, сообщите больше, если я пропустил баллы;) – GoGo

+0

BTW, это единственный способ создать ARRAY (а не срез) - это 'var array [] int'? – GoGo

Смежные вопросы