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.
В коде копируются значения из карты, а не создаётся копия среза (массива).
Почему в Go нет const map и const slice? Способы решения