dppfxf909679 2012-08-12 17:20
浏览 83
已采纳

在不同类型的切片之间转换

I get a byte slice ([]byte) from a UDP socket and want to treat it as an integer slice ([]int32) without changing the underlying array, and vice versa. In C(++) I would just cast between pointer types; how would I do this in Go?

  • 写回答

7条回答 默认 最新

  • dragonlew9876 2012-08-13 01:55
    关注

    As others have said, casting the pointer is considered bad form in Go. Here are examples of the proper Go way and the equivalent of the C array casting.

    WARNING: all code untested.

    The Right Way

    In this example, we are using the encoding/binary package to convert each set of 4 bytes into an int32. This is better because we are specifying the endianness. We are also not using the unsafe package to break the type system.

    import "encoding/binary"
    
    const SIZEOF_INT32 = 4 // bytes
    
    data := make([]int32, len(raw)/SIZEOF_INT32)
    for i := range data {
        // assuming little endian
        data[i] = int32(binary.LittleEndian.Uint32(raw[i*SIZEOF_INT32:(i+1)*SIZEOF_INT32]))
    }
    

    The Wrong Way (C array casting)

    In this example, we are telling Go to ignore the type system. This is not a good idea because it may fail in another implementation of Go. It is assuming things not in the language specification. However, this one does not do a full copy. This code uses unsafe to access the "SliceHeader" which is common in all slices. The header contains a pointer to the data (C array), the length, and the capacity. Instead of just converting the header to the new slice type, we first need to change the length and capacity since there are less elements if we treat the bytes as a new type.

    import (
        "reflect"
        "unsafe"
    )
    
    const SIZEOF_INT32 = 4 // bytes
    
    // Get the slice header
    header := *(*reflect.SliceHeader)(unsafe.Pointer(&raw))
    
    // The length and capacity of the slice are different.
    header.Len /= SIZEOF_INT32
    header.Cap /= SIZEOF_INT32
    
    // Convert slice header to an []int32
    data := *(*[]int32)(unsafe.Pointer(&header))
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(6条)

报告相同问题?

悬赏问题

  • ¥15 怎么把多于硬盘空间放到根目录下
  • ¥15 Matlab问题解答有两个问题
  • ¥50 Oracle Kubernetes服务器集群主节点无法访问,工作节点可以访问
  • ¥15 LCD12864中文显示
  • ¥15 在使用CH341SER.EXE时不小心把所有驱动文件删除了怎么解决
  • ¥15 gsoap生成onvif框架
  • ¥15 有关sql server business intellige安装,包括SSDT、SSMS。
  • ¥15 stm32的can接口不能收发数据
  • ¥15 目标检测算法移植到arm开发板
  • ¥15 利用JD51设计温度报警系统