Illustration composed from MariaLetta/free-gophers-pack , original gopher by Renee French. Warning! You should avoid using unsafe in your applications, unless you 100% sure what you are doing. It's called unsafe for a reason. Go is a strongly typed, you have to convert variable from one type to another to use in different parts of application. But sometimes you need to step around this type safety. It could be needed to optimization of bottle necks in high load systems, where every tick counts. Unsafe operation potentially could safe a lot of allocations. Unsafe also allows to hack into any struct field, including slices, strings, maps etc. Change string example String are immutable in Go. If you want to change a string, usually you have to allocate a new one. Let's hack Go a little bit with unsafe package, and actually change the string! main ( ) { a := + time.Now().String() fmt.Println(a) stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&a)) *(* )(unsafe.Pointer(stringHeader.Data + )) = fmt.Println(a) } package import "fmt" "reflect" "time" "unsafe" func main () "Hello. Current time is " byte 5 '!' Result: Hello. Current time is 2020-03-14 21:40:38.36328248 +0300 +03 m=+0.000037994 Hello! Current time is 2020-03-14 21:40:38.36328248 +0300 +03 m=+0.000037994 String is changed! Code snippet - https://play.golang.org/p/QJ6hIMz6_gg What's going on in this code? Following steps: Convert a string pointer to . Any pointer could be converted to and vise versa. also could be converted to - address in integer form. unsafe.Pointer unsafe.Pointer unsafe.Pointer uintptr Convert to pointer, to get Data pointer. type reflects string internal runtime struct. Under the hood string is represented by length value and pointer to memory with the data. unsafe.Pointer reflect.StringHeader reflect.StringHeader uintptr Move the pointer 5 bytes forward. With it is possible to do pointer arithmetic. uintptr Convert new to , and next to pointer. This byte is actually part of a string. uintptn unsafe.Pointer byte Assign new value to byte by pointer. String is changed! By the way, following code will produce segmentation violation error. Go compiler understands that string is constant and put it in memory along with other constants, where changes are forbidden. That's why I used in the first example. time.Now() main ( ) { a := fmt.Println(a) stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&a)) *(* )(unsafe.Pointer(stringHeader.Data + )) = fmt.Println(a) } package import "fmt" "reflect" "unsafe" func main () "Hello. Have a nice day!" byte 5 '!' Result: Hello. Have a nice day! unexpected fault address 0x4c3e31 fatal error: fault [signal SIGSEGV: segmentation violation code=0x2 addr=0x4c3e31 pc=0x48cf33] Code snippet - https://play.golang.org/p/ix70l38QvA4 Package unsafe Package consist of only 3 functions and single usable type. https://golang.org/pkg/unsafe/ func Alignof(x ArbitraryType) uintptr func Offsetof(x ArbitraryType) uintptr func Sizeof(x ArbitraryType) uintptr type Pointer *ArbitraryType type ArbitraryType // represents the type of an arbitrary Go expression, // not actually part of a package gives offset of field in struct. is a size of variable in memory, referenced memory not included. gives information regarding the alignment of variable address. Offsetof Sizeof Alignof Some examples of using and functions: unsafe.Offsetof unsafe.Sizeof Unsafe array iteration and type conversion on the fly with zero allocations. Getting information about the actual size of structs in memory. Changing struct field directly in memory, with struct pointer and field offset. main ( ) Bytes400 { val [ ] } TestStruct { a [ ] b c *Bytes400 d } { array := [ ] { , , , , , , , , , } sum sizeOfUint64 := unsafe.Sizeof(array[ ]) i := ( ); i < ; i++ { sum += *(* )(unsafe.Pointer( (unsafe.Pointer(&array)) + sizeOfUint64*i)) } fmt.Println(sum) t := TestStruct{b: } fmt.Println(unsafe.Sizeof(t)) fmt.Println(unsafe.Offsetof(t.a), unsafe.Offsetof(t.b), unsafe.Offsetof(t.c), unsafe.Offsetof(t.d)) fmt.Println(unsafe.Sizeof(Bytes400{})) *(* )(unsafe.Pointer( (unsafe.Pointer(&t)) + unsafe.Offsetof(t.b)))++ fmt.Println(t.b) } package import "fmt" "unsafe" type struct 100 int32 type struct 9 int64 byte int64 func main () 10 uint64 1 2 3 4 5 6 7 8 9 10 var int8 // Unsafe array iteration 0 for uintptr 0 10 int8 uintptr // Size of struct and offsets of struct fields 42 // Change struct field t.b value byte uintptr Result: 55 88 0 72 76 80 400 43 Code snippet - https://play.golang.org/p/cSmAUdu3sS9 Pointer arithmetic and garbage collector A can be converted to a and vise versa. Only way to perform pointer arithmetic is with usage of . General rule is that is an integer value without pointer semantics. It is not safe to use as an only pointer to object. Garbage collector unaware of it and object memory could be reused. It is best to convert it back to right away, after arithmetic operations are done. unsafe.Pointer uintptr uintptr uintptr uintptr unsafe.Pointer Benchmarks of unsafe string to []byte conversion main ( ) { (bytes) } { [] (s) } { sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&bytes)) *(* )(unsafe.Pointer(&reflect.StringHeader{ Data: sliceHeader.Data, Len: sliceHeader.Len, })) } { stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s)) *(*[] )(unsafe.Pointer(&reflect.SliceHeader{ Data: stringHeader.Data, Len: stringHeader.Len, Cap: stringHeader.Len, })) } package import "reflect" "unsafe" func SafeBytesToString (bytes [] ) byte string return string [] func SafeStringToBytes (s ) string byte return byte func UnsafeBytesToString (bytes [] ) byte string return string [] func UnsafeStringToBytes (s ) string byte return byte go -bench=. test Benchmark results: BenchmarkSafeBytesToString-8 257141380 4.50 ns/op BenchmarkSafeStringToBytes-8 227980887 5.38 ns/op BenchmarkUnsafeBytesToString-8 1000000000 0.305 ns/op BenchmarkUnsafeStringToBytes-8 1000000000 0.274 ns/op Unsafe conversion is more than 10 times faster! But this conversion only allocates new header, data remains the same. So if you change slice after conversion, string will also change. The following test will pass: { bs := [] ( ) str := UnsafeBytesToString(bs) str != { t.Fail() } bs[ ] = str != { t.Fail() } } func TestUnsafeBytesToString (t *testing.T) byte "Test" if "Test" // Test string mutation 0 't' if "test" If you really need to speed up conversions or hack inside go structures - use unsafe package. In other cases try to avoid it, it is not hard to mess something up with it. Thanks for reading and have a nice safe day! Repo with code samples: https://github.com/kochetkov-av/go-unsafe-type-conversions