英文:
Copy a struct content into uint64 in Go
问题
我想将一个结构体的值复制到uint64中,有没有不使用unsafe的正确方法?
package main
import "fmt"
type T struct {
id [7]byte
no uint8
}
func main() {
t1 := T{[7]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G'}, 7}
var u uint64
//TODO: 将t1的内容复制到u中(包括id和no)
//u = *((*uint64)(unsafe.Pointer(&t1)))
fmt.Println(t1, u)
}
英文:
I want to copy a strcuture's values into uint64, what's the proper method without unsafe?
package main
import "fmt"
type T struct {
id [7]byte
no uint8
}
func main() {
t1 := T{[7]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G'}, 7}
var u uint64
//TODO: copy t1's content into u (both id and no)
//u = *((*uint64)(unsafe.Pointer(&t1)))
fmt.Println(t1, u)
}
答案1
得分: 2
你试过类型转换了吗?
u = uint64(t1.no)
啊,好的。你试过使用binary.Write / binary.Read了吗?
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
type T struct {
id [7]byte
no uint8
}
func main() {
t1 := T{[7]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G'}, 7}
var u uint64
var b bytes.Buffer
binary.Write(&b, binary.LittleEndian, &t1)
binary.Read(&b, binary.LittleEndian, &u)
fmt.Println(t1, u)
}
但是请注意,binary包使用reflect包,reflect包使用unsafe包。
英文:
Did you try type cast?
u = uint64(t1.no)
Ah, ok. Did you try binary.Write / binary.Read ?
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
type T struct {
id [7]byte
no uint8
}
func main() {
t1 := T{[7]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G'}, 7}
var u uint64
var b bytes.Buffer
binary.Write(&b, binary.LittleEndian, &t1)
binary.Read(&b, binary.LittleEndian, &u)
fmt.Println(t1, u)
}
However, note that binary package uses reflect package, reflect package uses unsafe package.
答案2
得分: 2
例如,在小端架构上,不使用unsafe
包,
package main
import (
"fmt"
"unsafe"
)
type T struct {
id [7]byte
no uint8
}
func Uint64LEFromT(t T) uint64 {
return uint64(t.id[0]) | uint64(t.id[1])<<8 | uint64(t.id[2])<<16 | uint64(t.id[3])<<24 |
uint64(t.id[4])<<32 | uint64(t.id[5])<<40 | uint64(t.id[6])<<48 | uint64(t.no)<<56
}
func Uint64LEToT(t *T, v uint64) {
t.id[0] = byte(v)
t.id[1] = byte(v >> 8)
t.id[2] = byte(v >> 16)
t.id[3] = byte(v >> 24)
t.id[4] = byte(v >> 32)
t.id[5] = byte(v >> 40)
t.id[6] = byte(v >> 48)
t.no = byte(v >> 56)
}
func main() {
t1, t2 := T{[7]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G'}, 7}, T{}
var u1, u2 uint64
//TODO: 将t1的内容复制到u1(包括id和no)
u1 = *((*uint64)(unsafe.Pointer(&t1)))
fmt.Printf("t1 to u1 (unsafe): t1 %X u1 %X\n", t1, u1)
//DONE:
u2 = Uint64LEFromT(t1)
fmt.Printf("t1 to u2 (safe): t1 %X u2 %X\n", t1, u2)
Uint64LEToT(&t2, u2)
fmt.Printf("u2 to t2 (safe): t2 %X u2 %X\n", t2, u2)
}
输出:
t1 to u1 (unsafe): t1 {41424344454647 7} u1 747464544434241
t1 to u2 (safe): t1 {41424344454647 7} u2 747464544434241
u2 to t2 (safe): t2 {41424344454647 7} u2 747464544434241
英文:
For example, on little-endian architectures, without using package unsafe
,
package main
import (
"fmt"
"unsafe"
)
type T struct {
id [7]byte
no uint8
}
func Uint64LEFromT(t T) uint64 {
return uint64(t.id[0]) | uint64(t.id[1])<<8 | uint64(t.id[2])<<16 | uint64(t.id[3])<<24 |
uint64(t.id[4])<<32 | uint64(t.id[5])<<40 | uint64(t.id[6])<<48 | uint64(t.no)<<56
}
func Uint64LEToT(t *T, v uint64) {
t.id[0] = byte(v)
t.id[1] = byte(v >> 8)
t.id[2] = byte(v >> 16)
t.id[3] = byte(v >> 24)
t.id[4] = byte(v >> 32)
t.id[5] = byte(v >> 40)
t.id[6] = byte(v >> 48)
t.no = byte(v >> 56)
}
func main() {
t1, t2 := T{[7]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G'}, 7}, T{}
var u1, u2 uint64
//TODO: copy t1's content into u1 (both id and no)
u1 = *((*uint64)(unsafe.Pointer(&t1)))
fmt.Printf("t1 to u1 (unsafe): t1 %X u1 %X\n", t1, u1)
//DONE:
u2 = Uint64LEFromT(t1)
fmt.Printf("t1 to u2 (safe): t1 %X u2 %X\n", t1, u2)
Uint64LEToT(&t2, u2)
fmt.Printf("u2 to t2 (safe): t2 %X u2 %X\n", t2, u2)
}
Output:
t1 to u1 (unsafe): t1 {41424344454647 7} u1 747464544434241
t1 to u2 (safe): t1 {41424344454647 7} u2 747464544434241
u2 to t2 (safe): t2 {41424344454647 7} u2 747464544434241
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论