package main

import "fmt"

func main() {
	// len - размер слайса
	// cap - сколько аллоцировано памяти под слайс

	// создание
	var buf0 []int             // len = 0, cap = 0
	buf1 := []int{}            // len = 0, cap = 0
	buf2 := []int{42}          // len = 1, cap = 1
	buf3 := make([]int, 0)     // len = 0, cap = 0
	buf4 := make([]int, 5)     // len = 5, cap = 5
	buf5 := make([]int, 5, 10) // len = 5, cap = 10

	fmt.Println(buf0, buf1, buf2, buf3, buf4, buf5)

	// ошибка при выполнении
	// panic: runtime error: index out of range
	// someOtherInt := buf2[1]

	someInt := buf2[0]
	fmt.Println(someInt)

	// добавление элементов
	var buf []int            // len = 0, cap = 0
	buf = append(buf, 9, 10) // len = 2, cap = 2
	buf = append(buf, 12)    // len = 3, cap = 4

	// добавление другого слайса
	otherBuf := make([]int, 3)     // [0, 0, 0]
	buf = append(buf, otherBuf...) // len =6, cap = 8

	fmt.Println(buf, otherBuf)

	// просмотр информации о слайсе
	var bufLen, bufCap int = len(buf), cap(buf)

	fmt.Println(bufLen, bufCap)

	test1()
}

func test1() {
	buf := []int{1, 2, 3, 4, 5}
	fmt.Println(buf)
	// получение среза, указывающего на ту же память
	sl1 := buf[1:4] // [2, 3, 4]
	sl2 := buf[:2]  // [1, 2]
	sl3 := buf[2:]  // [3, 4, 5]
	fmt.Println(sl1, sl2, sl3)

	// Создать новый слайс - копия buf
	newBuf := buf[:] // [1, 2, 3, 4, 5]
	// изменив newBuf, buf тоже изменится
	// buf = [9, 2, 3, 4, 5], т.к. та же память
	newBuf[0] = 9

	// newBuf теперь указывает на другие данные
	newBuf = append(newBuf, 6)

	// при увеличении размера buf (дабвление данных)
	// он скопируется в другую область памяти,
	// И поэтому buf НЕ ИЗМЕНИТСЯ!!!!!

	// buf    = [9, 2, 3, 4, 5], не изменился
	// newBuf = [1, 2, 3, 4, 5, 6], изменился
	newBuf[0] = 1
	fmt.Println("buf", buf)
	fmt.Println("newBuf", newBuf)

	// копирование одного слайса в другой
	var emptyBuf []int // len=0, cap=0
	// неправильно - скопирует меньшее (по len) из 2-х слайсов
	copied := copy(emptyBuf, buf) // copied = 0
	fmt.Println(copied, emptyBuf)

	// правильно
	newBuf = make([]int, len(buf), len(buf))
	copy(newBuf, buf)
	fmt.Println(newBuf)

	// можно копировать в часть существующего слайса
	fmt.Println("Копирование в часть слайса:")
	ints := []int{1, 2, 3, 4}
	fmt.Println(ints)
	copy(ints[1:3], []int{5, 6}) // ints = [1, 5, 6, 4]
	fmt.Println(ints)
}
