文字列をバイト配列に割り当てる方法


375

文字列をバイト配列に割り当てたい:

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

別の方法がありますか?


11
の長さがの長さstrより大きい場合、arr「範囲外のインデックス」エラーが発生します。
peterSO

回答:


543

安全でシンプル:

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

14
ゴーのベストプラクティスのコーディングは、バイトのスライスを使用している[]byteいないバイトのセット配列[20]byteバイトに文字列を変換するときに... Doが私を信じていませんか?このスレッドで
openwonk

9
OPはスライスではなく配列について尋ねました。場合によっては、スライスのサイズを制限し、代わりに配列を使用する必要があります。以下の私の答えは、配列がオーバーフローしないように余分な文字をトリミングします。
DavidG

3
これが少し奇妙に見えると思う人のために:これはGoの型変換です:golang.org/ref/spec#Conversions
Cnly

複数の文字列を追加してそれらを連結させる方法はありますか?例えば[]byte("one", "two")
ラキム

残念ながら、@ rakimは1つの文字列しか渡せません。そのため、最初にそれらを連結するか、バイトの複数のスライスを組み合わせる必要があります(この質問の範囲外)。
openwonk

149

文字列からバイトスライスに変換する場合string -> []byte

[]byte(str)

配列をスライスに変換するには[20]byte -> []byte

arr[:]

文字列を配列にコピーする場合string -> [20]byte

copy(arr[:], str)

上記と同じですが、最初に文字列を明示的にスライスに変換します。

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

  • 組み込みcopy関数は、スライスからスライスにのみコピーます。
  • 配列は「基礎となるデータ」であり、スライスは「基礎となるデータへのビューポート」です。
  • を使用[:]すると、配列がスライスとして適格になります。
  • 文字列をコピーすることができますスライスとしての資格はありません、それをコピーすることができますスライスとしての資格から(文字列は不変です)。
  • 文字列が長すぎる場合、文字列のcopy収まる部分のみがコピーされます。

このコード:

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

...次の出力を提供します:

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

Go Playgroundでも利用できるようにしました


単一の文字を変換する例を追加することができます。私はこれからb[i] = []byte("A")[0]うまくいくと推測しb[i] = 'A'ましたが、最終的にはずっときれいになりました。
Alex Jansen

1
マルチバイトのルーンでは機能しません:b[1] = '本'
Alexander

110

例えば、

package main

import "fmt"

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

出力:

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
これが、元の質問に実際に対処する唯一の回答です。
Jack O'Connor

文字列に実際に必要なことについて具体的ではなく、なぜ20バイトを割り当てるのですか?文字列が20未満を必要とする場合、それは少し効率的ではありませんか?また、20を超えるとエラーが発生しやすくなりますか?
サー

1
@サー:私たちは20バイトを割り当てません。長さの3バイトをコピーしますs。`コピー機能はばかげていません。スライスへの追加とスライスのコピー:「コピーされる要素の数は、len(src)とlen(dst)の最小値です。」
peterSO 2017年

42

ケーキ:

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

8
これは質問に答えていないようです。OPは、文字列よりも長い可能性のある既存の配列に文字列のバイトを書き込みたいと考えていました。
Jack O'Connor

2
[]byte配列よりもスライスを使用することをお勧めします[20]byte。正解はベストプラクティスに基づいています。仕様またはコードで配列が必要な場合は、copy代わりに使用します(このスレッドの他の場所にある例を参照してください)。
openwonk

25

いいと思います。

package main

import "fmt"

func main() {
    str := "abc"
    mySlice := []byte(str)
    fmt.Printf("%v -> '%s'",mySlice,mySlice )
}

ここを確認してください:http : //play.golang.org/p/vpnAWHZZk7


3
それは良くない。それは間違っています。それは質問が要求したことをしません。
peterSO 2013

10

文字列をバイトスライスに変換します

[]文字列を[]バイト型に変換する高速な方法が必要です。テキストデータをランダムアクセスファイルに保存する場合や、入力データが[]バイトタイプである必要がある他のタイプのデータ操作などの状況で使用する場合。

package main

func main() {

    var s string

    //...

    b := []byte(s)

    //...
}

これは、データパラメータとしてバイトスライスを受け入れるioutil.WriteFileを使用するときに便利です。

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

もう一つの例

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)))
}

出力:

[104 101 108 108 111 32 119 111 114 108 100] hello world

リンク遊び場をご確認ください


0

これを行うには、アレイ固有のメソッドを作成することになりました。各int型に特定のメソッドを含むencoding / binaryパッケージによく似ています。例えば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)

出力:

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

右側ではなく左側にパディングが必要なことに注意してください。

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


3
答えに反対票を投じる場合は、なぜソリューションが最適ではないと思うのか、またはそれがOPの質問に関連しないのかについてコメントを残してください。
DavidG、2016年

3
逆投票はbyte16PutString、組み込みcopy関数の一種の再実装であり、既存の配列を使用する代わりに新しい配列の作成のみをサポートするためだと思います。copyは特別なコンパイラサポートを備えているため、さまざまなタイプの引数を処理できます。また、おそらく非常に高性能な実装が内部にあります。また、OPの質問は、新しい配列を割り当てるのではなく、既存の配列に文字列を書き込むことについて尋ねましたが、他のほとんどの回答もそれを無視しているようです...
Jack O'Connor

@ JackO'Connorに感謝します。私も学習のためにここにいて、単純な反対票だけでなく、建設的なフィードバックに感謝します。
DavidG

反対票answerが正しいことを知らないすべての組織が他の人々を学び、励ますためにここにいます
muthukumar helius

-1

上記の方法以外にも、次のようなトリックを実行できます。

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

Go Play:http : //play.golang.org/p/xASsiSpQmC

これは絶対に使用しないでください:-)


1
狂ってる。回答の最後に「すべきではない」を追加する価値はあると思います。それが実際に質問に答えないという事実(OPはスライスではなくバイト配列について話します)を除い[]byteて、「変換」を使用して適切なオブジェクトを取得するようには見えません-修正しようとするとひどく失敗しますpplay.golang.org/p/WHGl756ucj。あなたの場合、b := []byte(s)メソッドよりもなぜダブルアンセーフを好むのかわからない。
tomasz

1
@tomasz私はこの方法で文字列<-> [] byteを行うことを好まず、別のオプションを表示するだけです:-)そしてはい、あなたは正しいです、私は質問を誤解しました。
Brandon Gao

これを行うと、結果はcap()任意のサイズになります。つまり、未知のメモリに読み取っています。これが正しいためには、フルreflect.SliceHeaderサイズを割り当てて手動でを設定する必要があると思いますcap。次のようなもの:play.golang.org/p/fBK4dZM-qD
Lye Fish

そして、私はそれについてさえ確信がありません。-------------^-多分これはより良いかもしれません:play.golang.org/p/NJUxb20FTG
Lye Fish

-1

配列は値です...スライスはポインタのようなものです。基本的に2つの異なるもの[n]typeである[]typeため、これは互換性がありません。を使用して配列を指すスライスを取得できます。arr[:]これは、arrバッキングストレージとして持つスライスを返します。

例えばのスライスに変換するための一つの方法[]byteには[20]byte、実際に割り当てることである[20]byteあなたが使用して行うことができますvar [20]byte(それは、値なし...だとしてmake必要な)をし、それにデータをコピーします。

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

基本的に、他の多くの答えが間違っているのは、それ[]typeが配列ではないということです。

[n]Tそして、[]T全く異なるものです!

リフレクトを使用する場合[]T、種類はArrayではなく、種類はSliceで[n]T、種類はArrayです。

また、使用できませmap[[]byte]Tんが使用できますmap[[n]byte]T

たとえば多くの関数が動作するため、これは扱いにくい場合がありますが[]byte、一部の関数は戻ります[n]byte(特にのハッシュ関数crypto/*)。たとえば、sha256ハッシュは[32]byte[]byte初心者がファイルに書き込もうとすると、そうではありません。

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

エラーが発生します。正しい方法は使用することです

w.Write(sum[:])

しかし、あなたが望むのは何ですか?文字列にバイト単位でアクセスするだけですか?あなたは簡単にstring[]byte使用してに変換することができます:

bytes := []byte(str)

しかし、これは配列ではなく、スライスです。また、byte!= rune。「キャラクター」を操作したい場合はrune... を使用する必要がありますbyte

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.