Pull to refresh

Comments 12

Не понял. А зачем для копирования массива организуем цикл?

В языке что, нет способа скопировать массив в одну строчку?

нет. в Го вообще много чего нет. до сих пор упиваются своей стойкостью против введения тернарного оператора. зачем? разве кого-то напрягают 4 строчки вместо одной?

я хоть на Го уже не первый год, но прям сказать местами бесит :)

Ох. Как же это не очевидно, что под капотом операции присвоения будет выполнена операция копирования.

Вроде очевидно, вопрос только понимания что за структуру данных мы копируем(присваиваем). Слайсы и мапы (или любые другие структуры данных с указателями) содержат в себе указатели, соответственно логично что при присваивании мы скопируем поля структуры, в том числе указатель, а не сами данные куда он указывает. Та же история и с самим указателями, если нужно "скопировать" данные, на которые они ссылаются, вы это делаете отдельным действием.

Грубо говоря, ни у кого вроде не вызывает сомнения что делают строки ниже

var a string
b := a

m := &a
n := m

И что в случае с указателем мы "копируем" именно указатель, а не данные, на которые он указывает.

Лично я привык, что переменные - это не сами данные, а сущность позволяющая именованный доступ к данным. При этом не важно это данные, ссылка на данные или ссылка на ссылку на данные.

И когда я присваиваю "а" к "б", то не ожидаю, что произойдёт копирование.

Во многих языках именно так и произойдёт - копирования не будет.

Поэтому здесь это и не очевидно. Имея большой по размерам массив неожиданно получим в этой строке просадку по скорости / памяти.

Тем, кто приходит из других языков это будет неожиданно.

И когда я присваиваю "а" к "б", то не ожидаю, что произойдёт копирование.

Во многих языках именно так и произойдёт - копирования не будет.

Не совсем вас понимаю.

Давайте попробуем на простых примерах: есть у нас две переменные a и b типа string (под капотом кстати массив), что вы ожидаете(или не ожидаете) должно произойти(и происходит в других языках, но не происходит в Go) когда вы присваиваете

b = a

Можем продолжить про массив. Вот пример на Java:

https://www.programiz.com/online-compiler/2nS7QHhiZmTGp

В случае Java, C#, Rust, C/C++ под переменной a и b будет находиться одна и та же область памяти. В Go происходит неявное копирование.

Я отдаю себе отчёт, что это всё в Go происходит в рамках его спецификации. Претензий не имею. Просто отметил, что такое поведение не очень очевидно для тех, что пришёл из других языков в Go.

Понял, спасибо. Проблема получается в том что то что в других языках называется array, в Go ближе "по поведению" к своему типу slice, а то что в Go называется array как раз своя реализация с нюансами(array кстати лежит в основе slice под капотом).

Что-то в этом роде. Поэтому я всем кто у меня спрашивает как быстро перейти с одного языка на другой рекомендую кроме синтаксиса сосредоточиться на понятиях владения и неявного преобразования типов. Обычно эти вещи от языка к языку изменчивы и вполне способны привести к долго отлавливаемым багам.

built-in функцию copy для пришельцев придумали?)
Никто также не запрещает сделать append(dst, src...).
Всё это справедливо для слайсов, но никто не мешает кастить массивы в слайсы и назад, хоть это и муторно (append не сработал, но copy - вполне себе):

package main

import "fmt"

func main() {
	var a [2]int = [2]int{1, 2}
	var b [2]int

	fmt.Println(a)

	copy(b[:], a[:])
	fmt.Println(b)
}

В Go есть динамический массив (срез) и обычный массив. Для копирования среза можно воспользоваться функцией copy().

package main

import "fmt"

func main() {
	a := []int{1, 2, 3}
	b := make([]int, len(a))

	copy(b, a)
	b[2] = 4

	fmt.Println("a:", a)
	fmt.Println("b:", b)
}

Для копирования массива достаточно создать новую переменную.

package main

import "fmt"

func main() {
	arr1 := [...]int{1, 2, 3}
	arr2 := arr1

	arr2[2] = 4

	fmt.Println("arr1", arr1)
	fmt.Println("arr2", arr2)
}

Для создания копии карты можно воспользоваться пакетом maps.

В коде копируются значения из карты, а не создаётся копия среза (массива).

Sign up to leave a comment.