Praktik pengkodean terbaik di Go menggunakan sepotong byte []bytedan bukan set array byte [20]bytesaat mengkonversi string ke byte ... Jangan percaya padaku? Lihat jawaban Rob Pike di utas ini
openwonk
9
OP bertanya tentang sebuah array, bukan sepotong. Dalam beberapa kasus, Anda perlu membatasi ukuran slice dan menggunakan array. Jawaban saya di bawah memangkas karakter tambahan untuk memastikan Anda tidak melimpahi array.
cara apa pun untuk menambahkan beberapa string dan menyatukannya? misalnya []byte("one", "two")?
rakim
Sayangnya tidak, @rakim, Anda hanya dapat melewatkan satu string ... jadi, Anda harus menggabungkannya terlebih dahulu atau menggabungkan beberapa irisan byte (di luar cakupan pertanyaan ini).
openwonk
149
Untuk mengkonversi dari string ke sepotong byte, string -> []byte:
[]byte(str)
Untuk mengkonversi array untuk sepotong, [20]byte -> []byte:
arr[:]
Untuk menyalin string ke array, string -> [20]byte:
copy(arr[:], str)
Sama seperti di atas, tetapi secara eksplisit mengkonversi string menjadi slice terlebih dahulu:
copy(arr[:],[]byte(str))
Built-in copyfungsi hanya salinan untuk sepotong, dari sepotong.
Array adalah "data dasar", sedangkan irisan adalah "viewport ke dalam data dasar".
Menggunakan [:] membuat array memenuhi syarat sebagai slice.
Sebuah string tidak memenuhi syarat sebagai slice yang dapat disalin ke , tapi itu memenuhi syarat sebagai slice yang dapat disalin dari (string yang berubah).
Jika string terlalu panjang, copyhanya akan menyalin bagian dari string yang cocok.
Kode ini:
var arr [20]byte
copy(arr[:],"abc")
fmt.Printf("array: %v (%T)\n", arr, arr)
Anda mungkin ingin menambahkan contoh untuk mengonversi satu karakter. Saya menyimpulkan bahwa ini b[i] = []byte("A")[0]bekerja, tetapi b[i] = 'A'akhirnya menjadi jauh lebih bersih.
Alex Jansen
1
Itu tidak berfungsi untuk rune multi-byte:b[1] = '本'
Alexander
110
Sebagai contoh,
package main
import"fmt"
func main(){
s :="abc"var a [20]byte
copy(a[:], s)
fmt.Println("s:",[]byte(s),"a:", a)}
Ini adalah satu-satunya jawaban yang benar-benar menjawab pertanyaan awal.
Jack O'Connor
Mengapa menetapkan 20 byte daripada spesifik tentang yang sebenarnya Anda butuhkan untuk string? Jika string membutuhkan kurang dari 20 bukankah itu sedikit tidak efisien? Dan juga rawan kesalahan jika melebihi 20?
Sir
1
@ Sir: Kami tidak menetapkan 20 byte. Kami menyalin 3 byte, panjangnya s, `Fungsi salin tidak bodoh. Menambah dan menyalin irisan : "Jumlah elemen yang disalin adalah minimum len (src) dan len (dst)."
Ini sepertinya tidak menjawab pertanyaan. OP ingin menulis byte string ke array yang ada yang mungkin lebih panjang dari string.
Jack O'Connor
2
Menggunakan irisan []bytelebih disukai daripada array [20]byte. Jawabannya benar berdasarkan praktik terbaik; jika spesifikasi atau kode memerlukan array, maka gunakan copysebaliknya (lihat contoh di tempat lain di utas ini).
Itu tidak lebih baik. Itu salah. Tidak melakukan apa yang diminta pertanyaan itu.
peterSO
10
Pergi, konversikan string menjadi irisan byte
Anda memerlukan cara cepat untuk mengonversi string [] menjadi tipe [] byte. Untuk digunakan dalam situasi seperti menyimpan data teks ke file akses acak atau jenis manipulasi data lainnya yang membutuhkan data input berada dalam tipe byte [].
package main
func main(){var s string//...
b :=[]byte(s)//...}
yang berguna saat menggunakan ioutil.WriteFile, yang menerima irisan byte sebagai parameter datanya:
WriteFile func(filename string, data []byte, perm os.FileMode) error
Contoh lain
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)))}
Akhirnya menciptakan metode khusus array untuk melakukan ini. Sama seperti paket encoding / binary dengan metode spesifik untuk setiap tipe int. Sebagai contoh binary.BigEndian.PutUint16([]byte, uint16).
func byte16PutString(s string)[16]byte{var a [16]byteif 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)
Keluaran:
[0000000000000979899]
Perhatikan bagaimana saya ingin bantalan di sebelah kiri, bukan di kanan.
Jika Anda tidak memilih, silakan tinggalkan komentar tentang mengapa Anda menemukan solusi tidak optimal atau bagaimana itu tidak relevan dengan pertanyaan OP.
DavidG
3
Saya pikir downvotes karena byte16PutStringmerupakan semacam implementasi ulang dari copyfungsi builtin , yang hanya mendukung membuat array baru daripada menggunakan yang sudah ada. copymemiliki dukungan kompiler khusus, sehingga dapat menangani berbagai jenis argumen, dan mungkin memiliki implementasi yang sangat berkinerja tinggi di bawah selimut. Juga, pertanyaan OP bertanya tentang menulis string ke array yang ada, daripada mengalokasikan yang baru, meskipun sebagian besar jawaban lain tampaknya mengabaikan itu juga ...
Jack O'Connor
Terima kasih @ JackO'Connor saya di sini untuk pembelajaran juga dan menghargai umpan balik yang membangun, bukan hanya downvote biasa.
DavidG
tidak tahu kamu memilihnya answerbenar semua orang di sini untuk belajar dan mendorong orang lain
muthukumar helius
-1
Selain metode yang disebutkan di atas, Anda juga dapat melakukan trik sebagai
s :="hello"
b :=*(*[]byte)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&s))))
Ini gila. Saya pikir ini layak ditambahkan "tetapi Anda tidak boleh" di akhir tanggapan Anda. Terlepas dari kenyataan itu tidak benar-benar menjawab pertanyaan (OP berbicara tentang array byte, bukan irisan), Anda tampaknya tidak mendapatkan []byteobjek yang tepat menggunakan "konversi" Anda - gagal ketika Anda mencoba untuk mengubah p, lihat: play.golang.org/p/WHGl756ucj . Dalam kasus Anda, tidak yakin mengapa Anda lebih suka double-safe daripada b := []byte(s)metode ini.
tomasz
1
@ Thomasz Saya tidak suka melakukan byte <-> [] byte dengan cara ini, hanya menunjukkan opsi yang berbeda :-) dan ya Anda benar, saya salah paham pertanyaannya.
Brandon Gao
Ketika saya melakukan ini, hasilnya memiliki cap()ukuran sewenang-wenang, yang berarti membaca ke dalam memori yang tidak diketahui. Agar ini benar, saya pikir Anda harus memastikan Anda mengalokasikan reflect.SliceHeaderukuran penuh dan secara manual mengatur cap. Sesuatu seperti ini: play.golang.org/p/fBK4dZM-qD
Lye Fish
Dan saya bahkan tidak yakin akan hal itu .------------- ^ - Mungkin ini lebih baik: play.golang.org/p/NJUxb20FTG
Lye Fish
-1
Array adalah nilai ... irisan lebih seperti pointer. Itu adalah[n]type tidak sesuai dengan []typekarena mereka pada dasarnya adalah dua hal yang berbeda. Anda bisa mendapatkan slice yang menunjuk ke array dengan menggunakan arr[:]yang mengembalikan slice yang memiliki arrpenyimpanan backing.
Salah satu cara untuk mengkonversi sepotong misalnya []byteuntuk [20]byteadalah untuk benar-benar mengalokasikan [20]byteyang dapat Anda lakukan dengan menggunakanvar [20]byte (karena nilai ... tidak ada makeyang diperlukan) dan kemudian menyalin data ke dalamnya:
Pada dasarnya apa yang salah banyak jawaban lainnya adalah itu []typeBUKAN sebuah array.
[n]Tdan []Thal-hal yang sama sekali berbeda!
Saat menggunakan mencerminkan []T bukan dari jenis Array tetapi dari jenis Slice dan [n]Tjenis Array.
Anda juga tidak bisa menggunakan map[[]byte]T tetapi Anda bisa menggunakanmap[[n]byte]T .
Ini kadang-kadang bisa rumit karena banyak fungsi beroperasi misalnya di []bytesedangkan beberapa fungsi kembali [n]byte(terutama fungsi hash di crypto/*). Misalnya, hash sha256 adalah [32]bytedan tidak []bytedemikian ketika pemula mencoba menulisnya ke file misalnya:
sum := sha256.Sum256(data)
w.Write(sum)
mereka akan mendapatkan kesalahan. Cara yang benar adalah menggunakan
w.Write(sum[:])
Namun, apa yang Anda inginkan? Mengakses string secara langsung? Anda dapat dengan mudah mengonversi stringke []bytemenggunakan:
bytes :=[]byte(str)
tapi ini bukan sebuah array, ini adalah slice. Juga byte,! = rune. Jika Anda ingin beroperasi pada "karakter" yang perlu Anda gunakan rune... tidak byte.
str
lebih besar dari panjangnyaarr
maka Anda akan mendapatkan kesalahan "indeks di luar kisaran".Jawaban:
Aman dan sederhana:
sumber
[]byte
dan bukan set array byte[20]byte
saat mengkonversi string ke byte ... Jangan percaya padaku? Lihat jawaban Rob Pike di utas ini[]byte("one", "two")
?Untuk mengkonversi dari string ke sepotong byte,
string -> []byte
:Untuk mengkonversi array untuk sepotong,
[20]byte -> []byte
:Untuk menyalin string ke array,
string -> [20]byte
:Sama seperti di atas, tetapi secara eksplisit mengkonversi string menjadi slice terlebih dahulu:
copy
fungsi hanya salinan untuk sepotong, dari sepotong.[:]
membuat array memenuhi syarat sebagai slice.copy
hanya akan menyalin bagian dari string yang cocok.Kode ini:
... memberikan output berikut:
Saya juga membuatnya tersedia di Go Playground
sumber
b[i] = []byte("A")[0]
bekerja, tetapib[i] = 'A'
akhirnya menjadi jauh lebih bersih.b[1] = '本'
Sebagai contoh,
Keluaran:
sumber
s
, `Fungsi salin tidak bodoh. Menambah dan menyalin irisan : "Jumlah elemen yang disalin adalah minimum len (src) dan len (dst)."Sepotong kue:
sumber
[]byte
lebih disukai daripada array[20]byte
. Jawabannya benar berdasarkan praktik terbaik; jika spesifikasi atau kode memerlukan array, maka gunakancopy
sebaliknya (lihat contoh di tempat lain di utas ini).Saya pikir lebih baik ..
Periksa di sini: http://play.golang.org/p/vpnAWHZZk7
sumber
Pergi, konversikan string menjadi irisan byte
Anda memerlukan cara cepat untuk mengonversi string [] menjadi tipe [] byte. Untuk digunakan dalam situasi seperti menyimpan data teks ke file akses acak atau jenis manipulasi data lainnya yang membutuhkan data input berada dalam tipe byte [].
yang berguna saat menggunakan ioutil.WriteFile, yang menerima irisan byte sebagai parameter datanya:
Contoh lain
Keluaran:
Silakan periksa tautan bermain
sumber
Akhirnya menciptakan metode khusus array untuk melakukan ini. Sama seperti paket encoding / binary dengan metode spesifik untuk setiap tipe int. Sebagai contoh
binary.BigEndian.PutUint16([]byte, uint16)
.Keluaran:
Perhatikan bagaimana saya ingin bantalan di sebelah kiri, bukan di kanan.
http://play.golang.org/p/7tNumnJaiN
sumber
byte16PutString
merupakan semacam implementasi ulang daricopy
fungsi builtin , yang hanya mendukung membuat array baru daripada menggunakan yang sudah ada.copy
memiliki dukungan kompiler khusus, sehingga dapat menangani berbagai jenis argumen, dan mungkin memiliki implementasi yang sangat berkinerja tinggi di bawah selimut. Juga, pertanyaan OP bertanya tentang menulis string ke array yang ada, daripada mengalokasikan yang baru, meskipun sebagian besar jawaban lain tampaknya mengabaikan itu juga ...answer
benar semua orang di sini untuk belajar dan mendorong orang lainSelain metode yang disebutkan di atas, Anda juga dapat melakukan trik sebagai
Go Play: http://play.golang.org/p/xASsiSpQmC
Anda seharusnya tidak pernah menggunakan ini :-)
sumber
[]byte
objek yang tepat menggunakan "konversi" Anda - gagal ketika Anda mencoba untuk mengubahp
, lihat: play.golang.org/p/WHGl756ucj . Dalam kasus Anda, tidak yakin mengapa Anda lebih suka double-safe daripadab := []byte(s)
metode ini.cap()
ukuran sewenang-wenang, yang berarti membaca ke dalam memori yang tidak diketahui. Agar ini benar, saya pikir Anda harus memastikan Anda mengalokasikanreflect.SliceHeader
ukuran penuh dan secara manual mengaturcap
. Sesuatu seperti ini: play.golang.org/p/fBK4dZM-qDArray adalah nilai ... irisan lebih seperti pointer. Itu adalah
[n]type
tidak sesuai dengan[]type
karena mereka pada dasarnya adalah dua hal yang berbeda. Anda bisa mendapatkan slice yang menunjuk ke array dengan menggunakanarr[:]
yang mengembalikan slice yang memilikiarr
penyimpanan backing.Salah satu cara untuk mengkonversi sepotong misalnya
[]byte
untuk[20]byte
adalah untuk benar-benar mengalokasikan[20]byte
yang dapat Anda lakukan dengan menggunakanvar [20]byte
(karena nilai ... tidak adamake
yang diperlukan) dan kemudian menyalin data ke dalamnya:Pada dasarnya apa yang salah banyak jawaban lainnya adalah itu
[]type
BUKAN sebuah array.[n]T
dan[]T
hal-hal yang sama sekali berbeda!Saat menggunakan mencerminkan
[]T
bukan dari jenis Array tetapi dari jenis Slice dan[n]T
jenis Array.Anda juga tidak bisa menggunakan
map[[]byte]T
tetapi Anda bisa menggunakanmap[[n]byte]T
.Ini kadang-kadang bisa rumit karena banyak fungsi beroperasi misalnya di
[]byte
sedangkan beberapa fungsi kembali[n]byte
(terutama fungsi hash dicrypto/*
). Misalnya, hash sha256 adalah[32]byte
dan tidak[]byte
demikian ketika pemula mencoba menulisnya ke file misalnya:mereka akan mendapatkan kesalahan. Cara yang benar adalah menggunakan
Namun, apa yang Anda inginkan? Mengakses string secara langsung? Anda dapat dengan mudah mengonversi
string
ke[]byte
menggunakan:tapi ini bukan sebuah array, ini adalah slice. Juga
byte
,! =rune
. Jika Anda ingin beroperasi pada "karakter" yang perlu Anda gunakanrune
... tidakbyte
.sumber