Bayt dizisine dize atama


375

Bayt dizisine dize atamak istiyorum:

var arr [20]byte
str := "abc"
for k, v := range []byte(str) {
  arr[k] = byte(v)
}

Başka bir yönteminiz mi var?


11
Uzunluğu uzunluğundan strbüyükse, arr"aralık dışında bir dizin" hatası alırsınız.
peterSO

Yanıtlar:


543

Güvenli ve basit:

[]byte("Here is a string....")

14
Go Best kodlama uygulamaları bir bayt dilim kullanıyor []byteve olmayan bayt kümesidir dizisi [20]bytebayt bir dize dönüştürme ... Do bana inanmıyor? Bu
konudaki

9
OP bir dilim değil, bir dizi hakkında sordu. Bazı durumlarda, dilimin boyutunu sınırlamanız ve bunun yerine bir dizi kullanmanız gerekir. Aşağıdaki cevabım diziyi taşmadığınızdan emin olmak için ekstra karakterleri kesiyor.
DavidG

3
Bunun biraz garip göründüğünü düşünenler için: bu sadece Go'daki
Cnly

birden fazla dize eklemek ve bunları birleştirmek için herhangi bir yolu var mı? örneğin []byte("one", "two")?
rakim

Ne yazık ki hayır, @rakim, sadece bir dizeyi geçirebilirsiniz ... bu yüzden önce bunları birleştirmeniz veya birden çok bayt dilimini birleştirmeniz gerekir (bu sorunun kapsamı dışında).
openwonk

149

Bir dizeden bayt dilimine dönüştürmek için string -> []byte:

[]byte(str)

Bir diziyi bir dilime dönüştürmek için [20]byte -> []byte:

arr[:]

Bir dizeyi diziye kopyalamak için string -> [20]byte:

copy(arr[:], str)

Yukarıdaki ile aynı, ancak dizeyi açıkça bir dilime dönüştürüyoruz:

copy(arr[:], []byte(str))

  • Yerleşik copyişlevi yalnızca kopyaları için bir dilim, gelen bir dilim.
  • Diziler "temel veriler", dilimler ise "temel veriler için bir görünüm" dür.
  • Kullanmak [:], bir diziyi dilim olarak nitelendirir.
  • Bir dize kopyalanabilir dilim olarak nitelemek gelmez etmek , ancak kopyalanabilir dilim olarak nitelendirir dan (dizeleri iletmenin).
  • Dize çok uzunsa, copydizenin yalnızca uygun olan kısmını kopyalar.

Bu kod:

var arr [20]byte
copy(arr[:], "abc")
fmt.Printf("array: %v (%T)\n", arr, arr)

... şu çıktıyı verir:

array: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] ([20]uint8)

Ben ayrıca bu hazır Git Playground


Tek bir karakteri dönüştürmek için bir örnek eklemek isteyebilirsiniz. Bu işe b[i] = []byte("A")[0]yaradı, ama b[i] = 'A'çok daha temiz olur.
Alex Jansen

1
Bu çok baytlı runes için işe yaramaz:b[1] = '本'
Alexander

110

Örneğin,

package main

import "fmt"

func main() {
    s := "abc"
    var a [20]byte
    copy(a[:], s)
    fmt.Println("s:", []byte(s), "a:", a)
}

Çıktı:

s: [97 98 99] a: [97 98 99 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]

3
Asıl soruya cevap veren tek cevap budur.
Jack O'Connor

Neden dizeye gerçekten ihtiyacınız olduğundan ziyade 20 bayt atayın? Dize 20'den az gerekiyorsa bu bit verimsiz değil mi? Ve ayrıca 20'yi aşarsa eğilimli hata?
Efendim

1
@Sir: 20 bayt atamıyoruz. Biz 3 bayt kopya, uzunluğu s, `kopyalama işlevi aptal değil. Dilimlere ekleme ve kopyalama : "Kopyalanan öğelerin sayısı en az len (src) ve len (dst) 'dir."
peterSO

42

Kekin parçası:

arr := []byte("That's all folks!!")

8
Bu soruya cevap vermiyor gibi görünüyor. OP, dizenin baytlarını dizeden daha uzun olabilecek mevcut bir diziye yazmak istedi.
Jack O'Connor

2
Dizilere göre dilimlerin []bytekullanılması tercih edilir [20]byte. En iyi uygulamalara göre cevap doğrudur; teknik özellikler veya kod diziler gerektiriyorsa, copybunun yerine kullanın (bu iş parçacığının başka yerlerindeki örneklere bakın).
openwonk


10

Git, bir dizeyi bayt dilimine dönüştür

[] Dizesini [] bayt türüne dönüştürmenin hızlı bir yoluna ihtiyacınız vardır. Metin verilerinin rasgele erişim dosyasına veya giriş verilerinin [] bayt tipinde olmasını gerektiren başka bir veri işleme türü gibi durumlarda kullanmak için.

package main

func main() {

    var s string

    //...

    b := []byte(s)

    //...
}

veri parametresi olarak bir bayt dilimini kabul eden ioutil.WriteFile kullanılırken yararlıdır:

WriteFile func(filename string, data []byte, perm os.FileMode) error

Başka bir örnek

package main

import (
    "fmt"
    "strings"
)

func main() {

    stringSlice := []string{"hello", "world"}

    stringByte := strings.Join(stringSlice, " ")

    // Byte array value
    fmt.Println([]byte(stringByte))

    // Corresponding string value
    fmt.Println(string([]byte(stringByte)))
}

Çıktı:

[104101108101111 3211111111410100] Merhaba dünya

Lütfen bağlantı oyun alanını kontrol edin


0

Bunu yapmak için diziye özgü yöntemler oluşturma sona erdi. Her int türü için özel yöntemlerle kodlama / ikili pakete çok benzer . Örneğin binary.BigEndian.PutUint16([]byte, uint16).

func byte16PutString(s string) [16]byte {
    var a [16]byte
    if len(s) > 16 {
        copy(a[:], s)
    } else {
        copy(a[16-len(s):], s)
    }
    return a
}

var b [16]byte
b = byte16PutString("abc")
fmt.Printf("%v\n", b)

Çıktı:

[0 0 0 0 0 0 0 0 0 0 0 0 0 97 98 99]

Solda nasıl doldurmak istediğime dikkat edin, sağda değil.

http://play.golang.org/p/7tNumnJaiN


3
Cevabı oylamada yapıyorsanız, lütfen çözümü neden en uygun bulmuyorsanız veya OP'nin sorusuyla nasıl ilgili olmadığı hakkında bir yorum bırakın.
DavidG

3
Bence downvotes byte16PutStringyerleşik copyfonksiyonun bir tür yeniden uygulanması , çünkü sadece mevcut bir dizini kullanmak yerine yeni diziler oluşturmayı destekler. copyözel derleyici desteğine sahiptir, bu nedenle farklı türde argümanları işleyebilir ve muhtemelen kapakların altında gerçekten yüksek performanslı bir uygulamaya sahiptir. Ayrıca, OP'nin sorusu, diğer cevapların çoğu da bunu görmezden geliyor gibi görünse de, yeni bir tane ayırmak yerine mevcut bir diziye bir dize yazma hakkında sorular sordu ...
Jack O'Connor

Teşekkürler @ JackO'Connor Burada da öğrenim için varım ve sadece düz aşağı oyu değil, yapıcı geri bildirimi takdir ediyorum.
DavidG

bilmiyorum y aşağı answerdoğru oy her vücut öğrenmek ve teşvik etmek için burada
muthukumar helius

-1

Yukarıda belirtilen yöntemlerin yanı sıra,

s := "hello"
b := *(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))

Git oyna: http://play.golang.org/p/xASsiSpQmC

Bunu asla kullanmamalısınız :-)


1
Bu çılgınca. Cevabınızın sonunda "eklemelisiniz" eklemeye değer olduğunu düşünüyorum. Gerçekten soruyu cevaplamıyor olması dışında (OP, bayt dizisi hakkında konuşur, dilimler değil), []byte"dönüşümünüzü" kullanarak uygun bir nesne elde edemezsiniz - değiştirmeye çalıştığınızda kötü başarısız olur p, bkz: play.golang.org/p/WHGl756ucj . Sizin durumunuzda, b := []byte(s)yöntem üzerinde neden çift güvensizliği tercih edeceğinizden emin değilsiniz .
tomasz

1
@tomasz <-> [] baytını bu şekilde yapmayı tercih etmiyorum, sadece farklı bir seçenek gösteriyor :-) ve evet haklısın, soruyu yanlış anladım.
Brandon Gao

Bunu yaptığımda, sonucun cap()keyfi bir boyutu var, bu da bilinmeyen belleğe okuduğu anlamına geliyor. Bunun doğru olması için, tam reflect.SliceHeaderboyutu ayırdığınızdan ve manuel olarak ayarladığınızdan emin olmanız gerektiğini düşünüyorum cap. Bunun gibi bir şey: play.golang.org/p/fBK4dZM-qD
Lye Fish

Ve bundan bile emin değilim .------------- ^ - Belki de bu daha iyidir: play.golang.org/p/NJUxb20FTG
Lye Fish

-1

Diziler değerdir ... dilimler daha çok işaretçiler gibidir. Yani [n]typeuyumlu değil []typetemelden farklı şeylerdir olarak. Yedekleme depolama alanı arr[:]olan bir dilim döndüren bir diziyi işaret eden bir dilim alabilirsiniz arr.

Örneğin bir dilim dönüştürmek için bir yolu []byteiçin [20]byteaslında bir tahsis etmektir [20]bytekullanarak yapabileceğiniz hangi var [20]byte(bir değer olarak ... hayır makegerekli) ve daha sonra içine veri kopyalamak:

buf := make([]byte, 10)
var arr [10]byte
copy(arr[:], buf)

Aslında diğer cevapların bir çok yanlış yaptığı []typebir dizi DEĞİLDİR.

[n]Tve []Ttamamen farklı şeyler!

Yansıtmayı kullanırken []Ttür Array değil, Dilim tür ve [n]TArray türündedir.

Ayrıca kullanamazsınız map[[]byte]Tama kullanabilirsiniz map[[n]byte]T.

Bu bazen hantal olabilir çünkü birçok işlev örneğin üzerinde []byteçalışırken, bazı işlevler geri döner [n]byte(en önemlisi hash işlevleri crypto/*). Örneğin bir sha256 karması , yeni başlayanlar örneğin bir dosyaya yazmaya çalıştığında [32]bytedeğildir []byte:

sum := sha256.Sum256(data)
w.Write(sum)

bir hata alırlar. Doğru yolu kullanmak

w.Write(sum[:])

Ancak, ne istiyorsunuz? Sadece dizeye yavaş yavaş mı erişiyorsunuz? Kolayca bir dönüştürebilirsiniz stringiçin []bytekullanıyor:

bytes := []byte(str)

ama bu bir dizi değil, bir dilim. Ayrıca byte,! = rune. "Karakterler" üzerinde çalışmak istemeniz durumunda rune... kullanmanız gerekmiyor byte.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.