How do I use a (generic) vector in go? - vector

I am using a Vector type to store arrays of bytes (variable sizes)
store := vector.New(200);
...
rbuf := make([]byte, size);
...
store.Push(rbuf);
That all works well, but when I try to retrieve the values, the compiler tells me I need to use type assertions. So I add those in, and try
for i := 0; i < store.Len(); i++ {
el := store.At(i).([]byte);
...
But when I run this it bails out with:
interface is nil, not []uint8
throw: interface conversion
Any idea how I can 'cast'/convert from the empty Element interface that Vector uses to store its data to the actual []byte array that I then want to use subsequently?
Update (Go1): The vector package has been removed on 2011-10-18.

This works fine for me. Have you initialised the first 200 elements of your vector? If you didn't they will probably be nil, which would be the source of your error.
package main
import vector "container/vector"
import "fmt"
func main() {
vec := vector.New(0);
buf := make([]byte,10);
vec.Push(buf);
for i := 0; i < vec.Len(); i++ {
el := vec.At(i).([]byte);
fmt.Print(el,"\n");
}
}

Related

convert array of strings from CGO in GO

Can I convert an array of strings (char**) returned from a C (cgo) function in Go?
The code below compiles and runs, but I'm unable to range through a list of strings.
And I'm not even sure if it breaks the rules on "passing pointers": https://golang.org/cmd/cgo/
Any thoughts would be helpful, it's been years since I coded in C! Thanks in advance!
package main
/*
#include "stdlib.h"
char** getlist ()
{
char **array = NULL;
array = (char**)realloc(array, 2*sizeof(*array));
array[0]="HELLO";
array[1]="WORLD";
return array;
}
*/
import "C"
import (
"log"
"unsafe"
)
func main() {
list := C.getlist();
log.Printf("\n========\n C.getList()=%s", list)
ulist := unsafe.Pointer(list)
log.Printf("\n========\nulist=%s", ulist)
}
In order to iterate over the strings in Go, you need to convert the array to a Go slice. We can skip allocation here, and convert it directly (your example statically sets the length to 2, but in practice you would likely have another source for this size)
cSlice := (*[1 << 28]*C.char)(unsafe.Pointer(list))[:2:2]
We can iterate over this directly, and use the C.GoString function to convert the C strings. This is safer to store since it's copying the data to Go memory, but if this slice were exceptionally large we could save the allocation with the same unsafe conversion as above, though you would first need to find the length of each string.
var slice []string
for _, s := range (*[1 << 28]*C.char)(unsafe.Pointer(list))[:2:2] {
slice = append(slice, C.GoString(s))
}
After a couple hours of browsing, I found this concise solution (source):
list := C.getList()
length := 2
slice := make([]string, length)
for _, v := range unsafe.Slice(list, length) {
slice = append(slice, C.GoString(v))
}
For your length guessing issue, you can just make your C function take a pointer to a string array and return the size. It would then look like this:
var list **C.char
length := C.getList(&list)
slice := make([]string, length)
for _, v := range unsafe.Slice(list, length) {
slice = append(slice, C.GoString(v))
}

Behavior of a pointer to an element of `slice` after the `slice` had been appended to

I am wondering what is the behavior of a pointer to an element of slice after the slice had been appended to, for example:
package main
import "fmt"
func main() {
my_slice := []int {3}
silly_ptr := &my_slice[0]
// Do we know that silly_ptr points to value equal 3
// all the time? (If we don't explicitly change it).
fmt.Printf("%p\n", silly_ptr)
fmt.Println(*silly_ptr)
for i := 0; i < 10; i++ {
my_slice = append(my_slice, i)
}
silly_ptr_2 := &my_slice[0]
fmt.Printf("%p\n", silly_ptr_2)
fmt.Println(*silly_ptr_2)
}
Produces: (no surprises)
0xc20800a200
3
0xc20805a000
3
I know that when appending to dynamic array, at certain points we have repopulate the entire array, and therefore memory address of the original array elements is not reliable. To the best of my knowledge similar code is valid in c++, but silly_ptr could be pointing to anything. rust does not allow mutating a vector if it is being borrowed, so the above logic would not compile.
But what about Go? I know that by escape analysis it is valid to return a pointer to a local variable, the variable would be just created on the heap for you. My intuition tells me that the same logic applies in the above case. The memory location where silly_ptr is pointing to will not be repopulated, and hence will always store 3 (if we don't explictly change it). Is this right?
No, it will not always store 3.
Go has memory management. As long as there is an active pointer to an underlying array for a slice, the underlying array is pinned, it will not be garbage collected. If you have a pointer to an element of an underlying array, you can change the value of the element. For example,
package main
import (
"fmt"
)
func pin() *int {
s := []int{3}
fmt.Println(&s[0])
a := &s[0]
s = append(s, 7)
fmt.Println(&s[0])
return a
}
func main() {
a := pin()
fmt.Println(a, *a)
*a = 42
fmt.Println(a, *a)
}
Output:
0xc82000a340
0xc82000a360
0xc82000a340 3
0xc82000a340 42
A slice descriptor contains a pointer to an underlying array so you can see something similar with a slice. For example,
package main
import (
"fmt"
)
func pin() []int {
s := []int{3}
fmt.Println(&s[0])
d := s
s = append(s, 7)
fmt.Println(&s[0])
return d
}
func main() {
d := pin()
fmt.Println(&d[0], d)
d[0] = 42
fmt.Println(&d[0], d)
}
Output:
0xc82000a340
0xc82000a360
0xc82000a340 [3]
0xc82000a340 [42]

How get pointer of struct's member from interface{}

I want to pass struct's pointer to function that expect interface{}. Then get (through reflection) the pointer to the struct's member and then modify it using this pointer. I've read a much of Q&A and tried much of variations, but still I can get it work.
Let's consider example below:
type Robot struct {
Id int
}
f := func(i interface {}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Pointer()
*ptr = 100
//^ it needs to me for functions expecting the pointer: Scan(&pointerToValue)
}
robot := &Robot{}
f(robot)
println(robot.Id) //I want to get here 100
I think the problem in poor understanding what actually do Addr() and Pointer() methods of reflect package..
Here's a working version of function f:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
ptr := v.Addr().Interface().(*int)
*ptr = 100
}
playground example
The conversion to integer pointer goes as follows:
v is a reflect.Value representing the int field.
v.Addr() is a relfect.Value representing a pointer to the int field.
v.Addr().Interface() is an interface{} containing the int pointer.
v.Addr().Interface().(*int) type asserts the interface{} to a *int
You can set the field directly without getting a pointer:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
v.SetInt(100)
}
playground example
If you are passing the value along to something expecting interface{} (like the db/sql Scan methods), then you can remove the type assertion:
func f(i interface{}) {
v := reflect.ValueOf(i).Elem().FieldByName("Id")
scan(v.Addr().Interface())
}
playground example

How to convert from []byte to int in Go Programming

I need to create a client-server example over TCP. In the client side I read 2 numbers and I send them to the server. The problem I faced is that I can't convert from []byte to int, because the communication accept only data of type []byte.
Is there any way to convert []byte to int or I can send int to the server?
Some sample code will be really appreciated.
Thanks.
You can use encoding/binary's ByteOrder to do this for 16, 32, 64 bit types
Play
package main
import "fmt"
import "encoding/binary"
func main() {
var mySlice = []byte{244, 244, 244, 244, 244, 244, 244, 244}
data := binary.BigEndian.Uint64(mySlice)
fmt.Println(data)
}
If []byte is ASCII byte numbers then first convert the []byte to string and use the strconv package Atoi method which convert string to int.
package main
import (
"fmt"
"strconv"
)
func main() {
byteNumber := []byte("14")
byteToInt, _ := strconv.Atoi(string(byteNumber))
fmt.Println(byteToInt)
}
Go playground
Starting from a byte array you can use the binary package to do the conversions.
For example if you want to read ints :
buf := bytes.NewBuffer(b) // b is []byte
myfirstint, err := binary.ReadVarint(buf)
anotherint, err := binary.ReadVarint(buf)
The same package allows the reading of unsigned int or floats, with the desired byte orders, using the general Read function.
now := []byte{0xFF,0xFF,0xFF,0xFF}
nowBuffer := bytes.NewReader(now)
var nowVar uint32
binary.Read(nowBuffer,binary.BigEndian,&nowVar)
fmt.Println(nowVar)
4294967295
The math/big provides a simple and easy way to convert a binary slice to a number
playground
package main
import (
"fmt"
"math/big"
)
func main() {
b := []byte{0x01, 0x00, 0x01}
v := int(big.NewInt(0).SetBytes(b).Uint64())
fmt.Printf("%v", v)
}
For encoding/decoding numbers to/from byte sequences, there's the encoding/binary package. There are examples in the documentation: see the Examples section in the table of contents.
These encoding functions operate on io.Writer interfaces. The net.TCPConn type implements io.Writer, so you can write/read directly to network connections.
If you've got a Go program on either side of the connection, you may want to look at using encoding/gob. See the article "Gobs of data" for a walkthrough of using gob (skip to the bottom to see a self-contained example).
Using bitwise operator without additional dependencies
func toInt(bytes []byte) int {
result := 0
for i := 0; i < 4; i++ {
result = result << 8
result += int(bytes[i])
}
return result
}
binary.Read in encoding/binary provides mechanisms to convert byte arrays to datatypes.
Note that Network Byte Order is BigEndian, so in this case, you'll want to specify binary.BigEndian.
package main
import (
"bytes"
"encoding/binary"
"fmt"
)
func main() {
var myInt int
b := []byte{0x18, 0x2d} // This could also be a stream
buf := bytes.NewReader(b)
err := binary.Read(buf, binary.BigEndian, &myInt) // Make sure you know if the data is LittleEndian or BigEndian
if err != nil {
fmt.Println("binary.Read failed:", err)
return
}
fmt.Print(myInt)
}
Reviewing this documentation may be helpful: https://pkg.go.dev/encoding/binary#go1.17.1#Read
If bytes in the []byte array are ASCII characters from 0 to 9 you can convert them to an int in a loop:
var value int
for _, b := range []byte{48, 49, 50, 51, 52} {
value = value*10 + int(b-48)
}
fmt.Printf("integer value: %d", value)
Go Playground

Using a pointer to array

I'm having a little play with google's Go language, and I've run into something which is fairly basic in C but doesn't seem to be covered in the documentation I've seen so far
When I pass a pointer to a slice to a function, I presumed we'd have some way to access it as follows:
func conv(x []int, xlen int, h []int, hlen int, y *[]int)
for i := 0; i<xlen; i++ {
for j := 0; j<hlen; j++ {
*y[i+j] += x[i]*h[j]
}
}
}
But the Go compiler doesn't like this:
sean#spray:~/dev$ 8g broke.go
broke.go:8: invalid operation: y[i + j] (index of type *[]int)
Fair enough - it was just a guess. I have got a fairly straightforward workaround:
func conv(x []int, xlen int, h []int, hlen int, y_ *[]int) {
y := *y_
for i := 0; i<xlen; i++ {
for j := 0; j<hlen; j++ {
y[i+j] += x[i]*h[j]
}
}
}
But surely there's a better way. The annoying thing is that googling for info on Go isn't very useful as all sorts of C/C++/unrelated results appear for most search terms.
The Google Go docs state the following about passing arrays - they say you usually want to pass a slice (instead of a pointer?):
Updated:
As indicated by #Chickencha's comment, array slices are references which is why they are efficient for passing. Therefore likely you will want to use the slice mechanism instead of "raw" pointers.
From Google Effective Go doc http://golang.org/doc/effective_go.html#slices
Slices are reference types,
Original
It's under the heading
An Interlude about Types
[...snip...] When passing an array
to a function, you almost always want
to declare the formal parameter to be
a slice. When you call the function,
take the address of the array and Go
will create (efficiently) a slice
reference and pass that.
Editor's note: This is no longer the case
Using slices one can write this function (from sum.go):
09 func sum(a []int) int { // returns an int
10 s := 0
11 for i := 0; i < len(a); i++ {
12 s += a[i]
13 }
14 return s
15 }
and invoke it like this:
19 s := sum(&[3]int{1,2,3}) // a slice of the array is passed to sum
Maybe pass the whole array as a slice instead. Google indicates Go deals efficiently with slices. This is an alternate answer to the question but maybe it's a better way.
Types with empty [], such as []int are actually slices, not arrays. In Go, the size of an array is part of the type, so to actually have an array you would need to have something like [16]int, and the pointer to that would be *[16]int. So, what you are actually doing already is using slices, and the pointer to a slice, *[]int, is unnecessary as slices are already passed by reference.
Also remember that you can easily pass a slice referring to the entire array with &array (as long as the element type of the slice matches that of the array). (Not anymore.)
Example:
package main
import "fmt"
func sumPointerToArray(a *[8]int) (sum int) {
for _, value := range *a { sum += value }
return
}
func sumSlice (a []int) (sum int) {
for _, value := range a { sum += value }
return
}
func main() {
array := [...]int{ 1, 2, 3, 4, 5, 6, 7, 8 }
slice := []int{ 1, 2, 3, 4 }
fmt.Printf("sum arrray via pointer: %d\n", sumPointerToArray(&array))
fmt.Printf("sum slice: %d\n", sumSlice(slice))
slice = array[0:]
fmt.Printf("sum array as slice: %d\n", sumSlice(slice))
}
Edit: Updated to reflect changes in Go since this was first posted.
The semicolon and the asterisk are added and removed.
*y[i+j] += x[i]*h[j]
Is interpreted as
(*y)[i+j] += x[i] * h[j];
EDIT: Please read the comments. The answer is probably no longer valid. and I haven't touched up on go for quite some time and can't even read this anymore.
The length is part of the array's type, you can get length of an array by the len() built-in function. So you needn't pass the xlen, hlen arguments.
In Go, you can almost always use slice when passing array to a function. In this case, you don't need pointers.
Actually, you need not pass the y argument. It's the C's way to output array.
In Go style:
func conv(x, h []int) []int {
y := make([]int, len(x)+len(h))
for i, v := range x {
for j, u := range h {
y[i+j] = v * u
}
}
return y
}
Call the function:
conv(x[0:], h[0:])
Here's a working Go program.
package main
import "fmt"
func conv(x, h []int) []int {
y := make([]int, len(x)+len(h)-1)
for i := 0; i < len(x); i++ {
for j := 0; j < len(h); j++ {
y[i+j] += x[i] * h[j]
}
}
return y
}
func main() {
x := []int{1, 2}
h := []int{7, 8, 9}
y := conv(x, h)
fmt.Println(len(y), y)
}
To avoid wrong guesses, read the Go documentation: The Go Programming Language.
Almost all the other answers to this question talk about using slices instead of
array pointers but none answers how to solve the error, so I thought I would
write this answer. The error gives us a hint that it cannot access the index of
y because it is an invalid operation.
Your first approach is wrong as the Go compiler shouts at you. The problem in
the first approach is that *y[i+j] is wrong syntax. This is because
technically you are doing this *(y[i+j]) and you can't just do that because
y in your case is a pointer to an int array. If you print y it would print
the memory address of the array.
You are trying to get the i+jth index of y which does not simply exist
because y is not an array. You can fix your code by adding parentheses to the
statement which would indicate that you are trying to get the i+jth index of
the array that y is pointing to. Use (*y)[i+j] instead of *y[i+j]. The
function would look like this after making the changes:
func conv(x []int, xlen int, h []int, hlen int, y *[]int) {
for i := 0; i<xlen; i++ {
for j := 0; j<hlen; j++ {
(*y)[i+j] += x[i]*h[j]
}
}
}

Resources