From 6b71eb1ef78f2af56092ef3a29930d0c9d6fb2cb Mon Sep 17 00:00:00 2001 From: Wolfgang Welz <welzwo@gmail.com> Date: Thu, 1 Aug 2019 19:09:14 +0200 Subject: [PATCH] Use optimized version to convert bytes and string --- packages/typeutils/typeutils.go | 14 +------------- packages/typeutils/unsafe.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 13 deletions(-) create mode 100644 packages/typeutils/unsafe.go diff --git a/packages/typeutils/typeutils.go b/packages/typeutils/typeutils.go index eed90cf9..6bd97c88 100644 --- a/packages/typeutils/typeutils.go +++ b/packages/typeutils/typeutils.go @@ -1,22 +1,10 @@ package typeutils import ( - "reflect" "unsafe" ) -func BytesToString(b []byte) string { - bh := (*reflect.SliceHeader)(unsafe.Pointer(&b)) - - return *(*string)(unsafe.Pointer(&reflect.StringHeader{Data: bh.Data, Len: bh.Len})) -} - -func StringToBytes(str string) []byte { - hdr := (*reflect.StringHeader)(unsafe.Pointer(&str)) - - return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data: hdr.Data, Len: hdr.Len, Cap: hdr.Len})) -} - +// Checks whether an interface is nil or has the value nil. func IsInterfaceNil(param interface{}) bool { return param == nil || (*[2]uintptr)(unsafe.Pointer(¶m))[1] == 0 } diff --git a/packages/typeutils/unsafe.go b/packages/typeutils/unsafe.go new file mode 100644 index 00000000..56e8a996 --- /dev/null +++ b/packages/typeutils/unsafe.go @@ -0,0 +1,30 @@ +package typeutils + +import ( + "reflect" + "runtime" + "unsafe" +) + +// Converts a slice of bytes into a string without performing a copy. +// NOTE: This is an unsafe operation and may lead to problems if the bytes +// passed as argument are changed while the string is used. No checking whether +// bytes are valid UTF-8 data is performed. +func BytesToString(b []byte) string { + return *(*string)(unsafe.Pointer(&b)) +} + +// Converts a string into a slice of bytes without performing a copy. +// NOTE: This is an unsafe operation and may lead to problems if the bytes are changed. +func StringToBytes(s string) []byte { + sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) + b := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ + Data: sh.Data, + Len: sh.Len, + Cap: sh.Len, + })) + // ensure the underlying string doesn't get GC'ed before the assignment happens + runtime.KeepAlive(&s) + + return b +} -- GitLab