This is a creation in Article, where the information may have evolved or changed.
[]T
convert slices to[]byte
Convert other types of arrays to arrays in C-like languages char
:
func ByteSlice(slice interface{}) (data []byte) { sv := reflect.ValueOf(slice) if sv.Kind() != reflect.Slice { panic(fmt.Sprintf("ByteSlice called with non-slice value of type %T", slice)) } h := (*reflect.SliceHeader)((unsafe.Pointer(&data))) h.Cap = sv.Cap() * int(sv.Type().Elem().Size()) h.Len = sv.Len() * int(sv.Type().Elem().Size()) h.Data = sv.Pointer() return}
Based on this function, we can easily invoke []byte
the function of the type parameter:
func SaveImageData(name string, data []color.RGBA) error { return ioutil.WriteFile(name, ByteSlice(data), 0666)}
will be []X
converted to []Y
slices
The conversion of different types of arrays to each other, similar to the C language:
func Slice(slice interface{}, newSliceType reflect.Type) interface{} { sv := reflect.ValueOf(slice) if sv.Kind() != reflect.Slice { panic(fmt.Sprintf("Slice called with non-slice value of type %T", slice)) } if newSliceType.Kind() != reflect.Slice { panic(fmt.Sprintf("Slice called with non-slice type of type %T", newSliceType)) } newSlice := reflect.New(newSliceType) hdr := (*reflect.SliceHeader)(unsafe.Pointer(newSlice.Pointer())) hdr.Cap = sv.Cap() * int(sv.Type().Elem().Size()) / int(newSliceType.Elem().Size()) hdr.Len = sv.Len() * int(sv.Type().Elem().Size()) / int(newSliceType.Elem().Size()) hdr.Data = uintptr(sv.Pointer()) return newSlice.Elem().Interface()}
The conversion requires passing in a desired target tile type, interface{}
returning the converted slice as a form.
For example, in image processing, convert the RGB format to BGR format:
type RGB struct { R, G, B uint8}type BGR struct { B, G, R uint8}func RGB2BGR(data []RGB) []BGR { d := Slice(data, reflect.TypeOf([]BGR(nil))) return d.([]BGR)}
Like in C, the RGB
idea of converting a pointer to a BGR
pointer. The underlying structure of the data does not change.
Precautions
The conversion operation has a certain risk, the user needs to ensure their own security. These are mainly related to the following types:
- When a struct contains pointers, the conversion can cause garbage collection problems.
- If it is a
[]byte
turn []T
may cause the start address to be misaligned (it is []byte
possible to slice from an odd position).
- The conversion operation may depend on the current system, and there are differences between different types of processors.
The benefits of this conversion operation are performance and similar void*
generics, which are cgo
ideal for use with interfaces.