Map of channels - dictionary

I'd like to index some channels based on a string. I am using a map but it won't allow me to assign a channel to it. I keep getting "panic: assignment to entry in nil map", what am i missing?
package main
import "fmt"
func main() {
var things map[string](chan int)
things["stuff"] = make(chan int)
things["stuff"] <- 2
mything := <-things["stuff"]
fmt.Printf("my thing: %d", mything)
}
https://play.golang.org/p/PYvzhs4q4S

You need to initialize the map first. Something like:
things := make(map[string](chan int))
Another thing, you're sending and trying to consume from an unbuffered channel, so the program will be deadlocked. So may be use a buffered channel or send/consume in a goroutine.
I used a buffered channel here:
package main
import "fmt"
func main() {
things := make(map[string](chan int))
things["stuff"] = make(chan int, 2)
things["stuff"] <- 2
mything := <-things["stuff"]
fmt.Printf("my thing: %d", mything)
}
Playground link: https://play.golang.org/p/DV_taMtse5
The make(chan int, 2) part makes the channel buffered with a buffer length of 2. Read more about it here: https://tour.golang.org/concurrency/3

Related

Golang : convert Byte slice array to integer array

In Golang, the code [body, err := ioutil.ReadAll(resp.Body)], the ioutil.ReadAll() returns a byte Slice array, based on the documentation.
This is stored in the variable 'body'. My question is how to convert this byte Slice array, to an array of Integers.
I just found some code that does what I was wanting:
import "fmt"
import "strconv"
func main() {
var t = []string{"1", "2", "3"}
var t2 = []int{}
for _, i := range t {
j, err := strconv.Atoi(i)
if err != nil {
panic(err)
}
t2 = append(t2, j)
}
fmt.Println(t2)
}
So this code, does do what I want.
BUT l am disappointed in Golang, for not having a nice one liner that could do this
kind of conversion.
Certain basic things like this, should be packaged up for the programmer, and not have to do this kind of 'low' level programming.
Note, i still like Golang, they had done a lot to make a better C type language that has higher level Data Types when compared to C and also make some things more dynamic compared to C.
SO just disappointed they did not make a High Abstraction for this kind of case, which comes up quite a bit.

Golang: Why does increasing the size of a buffered channel eliminate output from my goroutines?

I am trying to understand why making the buffer size of a channel larger changes causes my code to run unexpectedly. If the buffer is smaller than my input (100 ints), the output is as expected, i.e., 7 goroutines each read a subset of the input and send output on another channel which prints it. If the buffer is the same size or larger than the input, I get no output and no error. Am I closing a channel at the wrong time? Do I have the wrong expectation about how buffers work? Or, something else?
package main
import (
"fmt"
"sync"
)
var wg1, wg2 sync.WaitGroup
func main() {
share := make(chan int, 10)
out := make(chan string)
go printChan(out)
for j:= 1; j<=7; j++ {
go readInt(share, out, j)
}
for i:=1; i<=100; i++ {
share <- i
}
close(share)
wg1.Wait()
close(out)
wg2.Wait()
}
func readInt(in chan int, out chan string, id int) {
wg1.Add(1)
for n := range in {
out <- fmt.Sprintf("goroutine:%d was sent %d", id, n)
}
wg1.Done()
}
func printChan(out chan string){
wg2.Add(1)
for l := range out {
fmt.Println(l)
}
wg2.Done()
}
To run this:
Small buffer, expected output. http://play.golang.org/p/4r7rTGypPO
Big buffer, no output. http://play.golang.org/p/S-BDsw7Ctu
This has nothing directly to do with the size of the buffer. Adding the buffer is exposing a bug in where you're calling waitGroup.Add(1)
You have to add to the WaitGroup before you dispatch the goroutine, otherwise you may end up calling Wait() before the waitGroup.Add(1) executes.
http://play.golang.org/p/YaDhc6n8_B
The reason it works in the first and not the second, is because the synchronous sends ensure that the gouroutines have executed at least that far. In the second example, the for loop fills up the channel, closes it and calls Wait before anything else can happen.

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 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

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

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");
}
}

Resources