2017-02-06 13 views
2

私はパケット構造を持っており、バイナリにシリアル化してワイヤで送ることができます。構造体を[]を使ってバイトに変換する

は、多くのパケット構造がありますが、私は例として、ログイン・パケットをあげる:

login struct { 
    seq  uint8 
    id  uint16 
    username [16]string 
    password [16]string 
    unknown1 [16]byte 
} 

私はあなたが非固定サイズの構造にbinary.Writeを使用できないことをどこかで読みました。しかし、私は自分の構造が固定されていると信じています(私が間違っていれば、私は間違っている可能性があります)。今binary.Write: invalid type main.login

、この問題を解決する方法があります:

var buf bytes.Buffer 
x := login{ 
    seq:  2, 
    id:  1, 
    username: [16]string{"username"}, 
    password: [16]string{"password"}, 
} 
err := binary.Write(&buf, binary.LittleEndian, x) 
if err != nil { 
    log.Fatalln(err) 
} 

は私にエラーを与える:

さて、このコードを使用していますか?別の方法がありますか? Cで構造体を使用してネットワーク経由で送信する方法とほとんど同じです。

+1

「[16] string'は実際には固定サイズではないと思いますか? – majidarif

+0

@CeriseLimónそうです。私は最大サイズの16バイトの文字列を書く必要があり、長さが16に達しない場合は\ 0で埋めます:) – majidarif

答えて

2

コードに2つのエラーがあります。まず、structフィールドをencoding/binaryにエクスポートして表示する必要があります。

第2に、[16]stringは、16バイト文字列ではなく16文字列の配列を意味します。だからあなたの構造体は次のようになります。

type login struct { 
    Seq  uint8 
    ID  uint16 
    Username [16]byte 
    Password [16]byte 
    Unknown1 [16]byte 
} 

そして、それは動作します:https://play.golang.org/p/Nq8fRqgkcp

+0

私の質問を再読している間に、私は実際にこの問題を認識しました。[16] string'私のコードで '[16] byte 'に変更しました。しかし、私は正直なところそれを初期化する方法を知らなかった。私も試みました: 'username:[16] byte {" username "}、'。とにかく、私はすぐにこの答えを受け入れます。 – majidarif

+0

@CeriseLimónはい、私はそれを見ました:) – majidarif

+0

@majidarif残念ながら、これらはスライスではなく_arrays_なので、文字列を使ってこれらのフィールドを設定する唯一の方法は、@ Ainar-Gが使用した 'copy()'構文です: 'コピー(l.Username [:]、" username ")'その構文は、スライスヘッダを 'Username'配列を指すようにし、そのスライスに文字列をコピーします。 – Kaedys

0

これはunsafeパッケージを使用して行うことができます。

type test struct { 
    a int 
    s string 
} 

v1 := test{ 
    a: 5, 
    s: "sdaf", 
} 

fmt.Printf("v1: %#v\n", v1) 

b := *(*[unsafe.Sizeof(v1)]byte)(unsafe.Pointer(&v1)) 
fmt.Printf("bytes: %#v\n", b) 

v2 := *(*test)(unsafe.Pointer(&b)) 

fmt.Printf("v2: %#v\n", v2) 
関連する問題