Marking question answered by copying JimB's answer from comment:
GoBytes copies a C allocated buffer into a slice with Go allocated memory. If that's what you want, then use GoBytes. Here you're not even keeping that copy, so there's no reason to do it.
Also, benchmark is interesting:
$ go test -bench . -benchmem
BenchmarkGoBytes-8 20000000 97.8 ns/op 32 B/op 3 allocs/op
BenchmarkDirect-8 2000000000 0.84 ns/op 0 B/op 0 allocs/op
PASS
Answer from Mark on Stack OverflowGo Packages
pkg.go.dev › cmd › cgo
cgo command - cmd/cgo - Go Packages
April 7, 2026 - // It is the caller's responsibility to arrange for it to be // freed, such as by calling C.free (be sure to include stdlib.h // if C.free is needed). func C.CBytes([]byte) unsafe.Pointer // C string to Go string func C.GoString(*C.char) string // C data with explicit length to Go string func C.GoStringN(*C.char, C.int) string // C data with explicit length to Go []byte func C.GoBytes(unsafe.Pointer, C.int) []byte
proposal: runtime/cgo: move built-in C helpers from cmd/cgo to runtime/cgo
The proposed API is almost the same as the one already generated by runtime/cgo, with the only difference that GoStringN and GoBytes accept an int instead of a C.int as length parameter. More on github.com
cgo: Feature request for convenience function C.GoBytes(char*, int) []byte
GoBytes() would be similar to GoStringN(), except that it would return a byte slice. This will avoid an extra copy if the application wanted a byte slice instead of a string. More on github.com
proposal: cmd/cgo: change GoStringN, GoBytes to take C.size_t
Change the signature of GoStringN(*C.char, C.int) to GoStringN(*C.char, C.size_t), and similarly for GoBytes. This would enable C->Go transfer of >2GB strings on most Go systems, and avoid a cast when wrapping C APIs that follow modern usage guidelines · This would also improve consistency ... More on github.com
Darwin CPU info: C.GoBytes: cgo argument has Go pointer to Go pointer
For macOS, the CPU times are read via a cgo call to host_processor_info. The result of the operation is a chunk of memory allocated by the kernel, which the Go code needs to copy to its own GC-ed m... More on github.com
Videos
r/golang on Reddit: Why CGO is Dangerous
10:38
Using C and Go with CGO is tricky - YouTube
Calling C code from Go
05:29
How to Embed C code in Golang: Example Tutorial - YouTube
05:17
How to use the Go language's cgo package to interface with C - YouTube
Cgo - Adding C code to your Go project - YouTube
Go
go.dev › wiki › cgo
Go Wiki: cgo - The Go Programming Language
func C.GoBytes(cArray unsafe.Pointer, length C.int) []byte ·
Google Groups
groups.google.com › g › golang-nuts › c › R67yt3Dz3tw
Where are cgo C.* helper functions implemented and is there godoc for them?
The source code is in cmd/cgo/out.go: //go:linkname _cgo_runtime_gobytes runtime.gobytes func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte { return _cgo_runtime_gobytes(p, int(l)) } The call to _cgo_runtime_gobytes will call runtime.gobytes, which is defined in runtime/string.go.
Karthikkaranth
karthikkaranth.me › blog › calling-c-code-from-go
Calling C code from go | Karthik Karanth
Here, we convert the C buffer to a go []byte object. The cgo function C.GoBytes does this for us, using the pointer and the size of the written data. The byte slice returned does not share memory with the bytes we allocated using malloc.
GitHub
github.com › golang › go › issues › 51134
proposal: runtime/cgo: move built-in C helpers from cmd/cgo to runtime/cgo · Issue #51134 · golang/go
February 10, 2022 - func GoBytes(p unsafe.Pointer, l int) []byte // CString converts the Go string s to a C string. // // The C string is allocated in the C heap using malloc. // It is the caller's responsibility to arrange for it to be // freed, such as by calling C.free (be sure to include stdlib.h // if C.free is needed).
Author qmuntal
Lobaro
lobaro.com › en › embedded-development-with-c-and-golang-cgo
Embedded development with C and GoLang (CGO) – Lobaro.com
func go_handleData(data *C.uint8_t, length C.uint8_t) []byte { return C.GoBytes(unsafe.Pointer(data), C.int(length)) }
Chris's Wiki
utcc.utoronto.ca › ~cks › space › blog › programming › GoCGoStringFunctions
Chris's Wiki :: blog/programming/GoCGoStringFunctions
August 31, 2015 - C.GoBytes() is a version of C.GoStringN() that returns a []byte instead of a string.
GitHub
github.com › golang › go › issues › 1640
cgo: Feature request for convenience function C.GoBytes(char*, int) []byte · Issue #1640 · golang/go
November 12, 2016 - golang / go Public · Notifications · You must be signed in to change notification settings · Fork 18.4k · Star 130k · New issueCopy link · New issueCopy link · Closed · Closed · cgo: Feature request for convenience function C.GoBytes(char*, int) []byte#1640 ·
Author sougou
HotExamples
golang.hotexamples.com › examples › c › - › GoBytes › golang-gobytes-function-examples.html
Golang GoBytes Examples, C.GoBytes Golang Examples - HotExamples
func (self *KcDb) Iter(fun func(string, Getter) bool) { cur := C.kcdbcursor(self.cdb) C.kccurjump(cur) var kSize, vSize C.size_t var vBuff, kBuff *C.char var ret bool for { kBuff = C.kccurget(cur, &kSize, &vBuff, &vSize, kcTrue) if kBuff == nil { C.kcfree(unsafe.Pointer(kBuff)) break } key := string(C.GoBytes(unsafe.Pointer(kBuff), C.int(kSize))) value := C.GoBytes(unsafe.Pointer(vBuff), C.int(vSize)) r := bytes.NewReader(value) ret = fun(key, func(e interface{}) error { return decode(r, e) }) C.kcfree(unsafe.Pointer(kBuff)) if ret == false { break } } C.kccurdel(cur) }
Zchee
zchee.github.io › golang-wiki › cgo
cgo - Go Programming Language Wiki
Go provides the following function to make a new Go byte slice from a C array: * func C.GoBytes(cArray unsafe.Pointer, length C.int) []byte ·
GitHub
gist.github.com › zchee › b9c99695463d8902cd33
cgo convert list · GitHub
// Go string to C string; result must be freed with C.free func C.CString(string) *C.char // C string to Go string func C.GoString(*C.char) string // C string, length to Go string func C.GoStringN(*C.char, C.int) string // C pointer, length to Go []byte func C.GoBytes(unsafe.Pointer, C.int) []byte · type C.char type C.schar (signed char) type C.uchar (unsigned char) type C.short type C.ushort (unsigned short) type C.int type C.uint (unsigned int) type C.long type C.ulong (unsigned long) type C.longlong (long long) type C.ulonglong (unsigned long long) type C.float · type C.double · As in C.struct_stat · type C.struct_*** type C.union_*** type C.enum_*** See also https://golang.org/pkg/unsafe/ func unsafe.Pointer() *ArbitraryType ·
GitHub
github.com › golang › go › issues › 61361
proposal: cmd/cgo: change GoStringN, GoBytes to take C.size_t · Issue #61361 · golang/go
July 14, 2023 - Change the signature of GoStringN(*C.char, C.int) to GoStringN(*C.char, C.size_t), and similarly for GoBytes. This would enable C->Go transfer of >2GB strings on most Go systems, and avoid a cast when wrapping C APIs that follow modern usage guidelines · This would also improve consistency ...
Author bemasc
Google Groups
groups.google.com › g › golang-nuts › c › PwIFiz9AhVg
Right way to convert c char to golang bytes
Can you post some code that reproduces the C.GoBytes() behavior you see? According to the documentation it should work as you expect. This "simulation" works (but can not be run in the playground because of cgo usage): https://play.golang.org/p/gec7VNy4-UW
GitHub
github.com › shirou › gopsutil › issues › 279
Darwin CPU info: C.GoBytes: cgo argument has Go pointer to Go pointer · Issue #279 · shirou/gopsutil
November 13, 2016 - If the memory that the kernel allocates is within a region which the Go runtime believes that it may be used by the GC, the call to C.GoBytes will panic with "cgo argument has Go pointer to Go pointer". This happens fairly regularly for me when running a binary with gopsutil linked in under the Delve debugger. One workaround (works for me, but untested in production; macOS only for development) is to create a slice which is directly backed by the system memory (which is freed by C code), as described in https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices ·
Author lowjoel
Top answer 1 of 2
11
The easiest and safest way is to copy it to a slice, not specifically to [1024]byte
mySlice := C.GoBytes(unsafe.Pointer(&C.my_buff), C.BUFF_SIZE)
To use the memory directly without a copy, you can "cast" it through an unsafe.Pointer.
mySlice := unsafe.Slice((*byte)(unsafe.Pointer(&C.my_buf)), C.BUFF_SIZE)
// and if you need an array type, the slice can be converted
myArray := ([C.BUFF_SIZE]byte)(mySlice)
2 of 2
1
To create a Go slice with the contents of C.my_buf:
arr := C.GoBytes(unsafe.Pointer(&C.my_buf), C.BUF_SIZE)
To create a Go array...
var arr [C.BUF_SIZE]byte
copy(arr[:], C.GoBytes(unsafe.Pointer(&C.my_buf), C.BUF_SIZE))
GitHub
github.com › andreiavrammsd › cgo-examples › blob › master › main.go
cgo-examples/main.go at master · andreiavrammsd/cgo-examples
stringBytes := C.GoBytes(unsafe.Pointer(C.get_string()), 24) fmt.Println(stringBytes[0:bytes.Index(stringBytes, []byte{0})]) fmt.Println() · // Send string · fmt.Println("Send string") str := "lorem ipsum" cStr := C.CString(str) C.print_string(cStr) C.free(unsafe.Pointer(cStr)) fmt.Println() ·
Author andreiavrammsd
Akrennmair
akrennmair.github.io › golang-cgo-slides
Go & cgo: integrating existing C code with Go
// Go string to C string; result must be freed with C.free func C.CString(string) *C.char // C string to Go string func C.GoString(*C.char) string // C string, length to Go string func C.GoStringN(*C.char, C.int) string // C pointer, length to Go []byte func C.GoBytes(unsafe.Pointer, C.int) []byte · Go code can be exported via comment: //export <function-name> It can then be called from C · package foo /* extern void myprint(int i); void dofoo(void) { int i; for (i=0;i<10;i++) { myprint(i); } } */ import "C" //export myprint func myprint(i C.int) { fmt.Printf("i = %v\n", uint32(i)) } func DoFoo() { C.dofoo() } Useful Links: Slides: http://akrennmair.github.com/golang-cgo-slides/ gopcap: https://github.com/akrennmair/gopcap ·