Является ли slice2: = slice1 равным slice2: = slice1 [:] в GoLang? - PullRequest
0 голосов
/ 27 ноября 2018

Две следующие строки кода делают то же самое в GoLang?Я хочу скопировать фрагмент в другой:

slice1 := make([]int, 5)
slice2 := slice1 #line1
slice2 := slice1[:] #line2

Я запускаю этот код, чтобы проверить поведение, но, очевидно, они оба работают одинаково:

func main() {
    s1 := make([]int, 5, 5)
    s1[2] = 33
    fmt.Printf("s1: %v: address of slice %p\n", s1, &s1)
    s2 := s1[:]
    s2[1] = 5
    fmt.Printf("s2: %v: address of slice %p\n", s2, &s2)
    s3 := s1
    s3[0] = 23
    fmt.Printf("s3: %v: address of slice %p\n",s3, &s3)
    fmt.Printf("s2: %v: address of slice %p\n", s2, &s2)
    fmt.Printf("s1: %v: address of slice %p\n", s1, &s1)
}

Вывод:

s1: [0 0 33 0 0]: address of slice 0x40c0e0
s2: [0 5 33 0 0]: address of slice 0x40c100
s3: [23 5 33 0 0]: address of slice 0x40c120
s2: [23 5 33 0 0]: address of slice 0x40c100
s1: [23 5 33 0 0]: address of slice 0x40c0e0

Таким образом, адреса памяти срезов (s1, s2, s3) разные, но указатели на содержащиеся в них массивы указывают на один и тот же адрес памяти.

Мне интересно, есть ли что-то, что меняется между этими двумя способами, или есть какое-то соглашение, которое говорит, что лучше использовать.

1 Ответ

0 голосов
/ 27 ноября 2018

Результат тот же.

Одна вещь, которую вы не проверяли, - это емкость, другое свойство срезов.Итак, давайте проверим это тоже:

s := make([]int, 2, 4)
s2 := s
s3 := s[:]

fmt.Println(len(s), cap(s))
fmt.Println(len(s2), cap(s2))
fmt.Println(len(s3), cap(s3))

Вывод (попробуйте на Go Playground ):

2 4
2 4
2 4

В основном выражение среза s[:] означает нарезку среза и использование 0 в качестве нижнего индекса, len(s) в качестве верхнего и cap(s) в качестве емкости.Таким образом, результатом будет срез, идентичный s.

. Для удобства чтения просто скопируйте заголовок среза: s2 := s.

Также обратите внимание, что если s будет nilи копирование, и нарезка его также приведет к получению nil фрагментов:

var s []int
s2 := s
s3 := s[:]

fmt.Println(len(s), cap(s), s == nil)
fmt.Println(len(s2), cap(s2), s2 == nil)
fmt.Println(len(s3), cap(s3), s3 == nil)

Вывод вышеизложенного (попробуйте на Go Playground ):

0 0 true
0 0 true
0 0 true

Так что нет абсолютно никакой разницы в результате.Реализация компилятора может или не может имитировать оператор s2 := s, когда вы пишете s2 := s[:], поэтому последний может быть медленнее.Но опять же, нет причин не просто копировать его.

...