2016-10-12 35 views
13

Golang'da, seyahat eden satıcı problemim için bir karıştırma dilimi işlevi yapmaya çalışıyorum. Yaptığım dilimi düzenlemeye başladığımda fark ettim ki, her defasında, scramble işlevi farklıydı.Golang dilimleri değere mi geçiyor?

Bazı hata ayıklama işleminden sonra, dilimin fonksiyonun içinde düzenlenmesinden kaynaklandığını öğrendim. Ancak Golang'ın "değerden geçmek" dilinden olması gerektiğinden, bu nasıl mümkün olabilir?

https://play.golang.org/p/mMivoH0TuV

Ben ne demek istediğimi göstermek için oyun alanı bağlantısını sağladık. Satır 27'yi çıkararak, onu bırakmaktan farklı bir çıktı elde edersiniz, bu işlev, bir argüman olarak iletildiğinde dilimin kendi kopyasını oluşturması gerektiği için bir fark yaratmamalıdır.
Birisi fenomeni açıklayabilir mi?

cevap

28

Evet, Go'daki her şey değere göre geçirilir. Dilimler de. Ancak, bir dilim değeri, bir yedekleme dizisinin bitişik bir bölümünü açıklayan başlığı ve bir dilim değeri, öğelerin gerçekten depolandığı diziye yalnızca bir gösterici içerir. Dilim değeri öğelerini içermez (dizilerden farklı olarak).

Böylelikle bir dilimi bir işleve ilettiğinizde, aynı üstbilgisi dizisine işaret eden işaretçi de dahil olmak üzere, bu başlıktan bir kopya yapılacaktır. Dilimin elemanlarının değiştirilmesi, destek dizisinin elemanlarının değiştirilmesini ifade eder, ve böylece aynı destek dizisini paylaşan tüm dilimler değişikliği "gözlemleyecektir".

reflect.SliceHeader türünü göz atın bir dilim başlığında ne olduğunu görmek için:

type SliceHeader struct { 
    Data uintptr 
    Len int 
    Cap int 
} 

ilgili/olası yinelenen soruya bakın: Are Golang function parameter passed as copy-on-write?

Oku blog yazısı: Go Slices: usage and internals

+0

böylece olur bir çözüm Dilimin yerel bir kopyasını işlev içinde yapmak. ve bunun yerine düzenleme mi? – duck

+1

@ user4901806 Geçilen dilimin elemanlarını değiştirmek istemiyorsanız (destek dizisinin öğeleri işaret eder), evet, bir kopya oluşturun. – icza

+0

Bunun bir öğe eklersek, orijinal dilime eklenmeyeceği anlamına gelir. – Sahas