How to instantiate this map of structs - go

Here is my struct and instantiation:
type mxSet struct {
domainLock sync.RWMutex
connections []chan *decodejson.RcptEntity
}
var connMap = make(map[string]*mxSet)
How do I make a buffered channel when it's inside a struct inside a map? These channels correspond to TCP connections I have open, so I need to be able to dynamically open/close them.
How do I also instantiate the sync.RWMutex at the same time?
More context: What I am trying to do is maintain a map of TCP connections open to a domain. The []chan is how I send data into a specific TCP connections for a specific domain.
Please offer a conceptual explanation of what needs to happen here as well as code.

If no value is in the map, then create the value and add to the map.
mx, ok := connMap[key]
if !ok {
mx = &mxSet{}
connMap[key] = mx
}
... use mx as needed needed.
The zero values of the sync.RwMutex and the slice of channels are ready to use. No code is required to set them up.

Related

How to implement a singleton

I want to implement a singleton with Go. The difference between normal singleton is the instance is singleton with different key in map struct. Something like this code. I am not sure is there any data race with the demo code.
var instanceLock sync.Mutex
var instances map[string]string
func getDemoInstance(key string) string {
if value, ok := instances[key]; ok {
return value
}
instanceLock.Lock()
defer instanceLock.Unlock()
if value, ok := instances[key]; ok {
return value
} else {
instances[key] = key + key
return key + key
}
}
Yes, there is data race, you can confirm by running it with go run -race main.go. If one goroutine locks and modifies the map, another goroutine may be reading it before the lock.
You may use sync.RWMutex to read-lock when just reading it (multiple readers are allowed without blocking each other).
For example:
var (
instancesMU sync.RWMutex
instances = map[string]string{}
)
func getDemoInstance(key string) string {
instancesMU.RLock()
if value, ok := instances[key]; ok {
instancesMU.RUnlock()
return value
}
instancesMU.RUnlock()
instancesMU.Lock()
defer instancesMU.Unlock()
if value, ok := instances[key]; ok {
return value
}
value := key + key
instances[key] = value
return value
}
You can try this as well: sync.Map
Map is like a Go map[interface{}]interface{} but is safe for concurrent use by multiple goroutines without additional locking or coordination. Loads, stores, and deletes run in amortized constant time.
The Map type is optimized for two common use cases: (1) when the entry for a given key is only ever written once but read many times, as in caches that only grow, or (2) when multiple goroutines read, write, and overwrite entries for disjoint sets of keys.
In these two cases, use of a Map may significantly reduce lock contention compared to a Go map paired with a separate Mutex or RWMutex.
Note: In the third paragraph it mentions why using sync.Map is beneficial rather than using Go Map simply paired up with sync.RWMutex.
So this perfectly fits your case, I guess?
Little late to answer, anyways this should help: https://github.com/ashwinshirva/api/tree/master/dp/singleton
This shows two ways to implement singleton:
Using the sync.Mutex
Using sync.Once

Break out of 3rd party goroutine that has an infinite loop

I'm using this to receive SNMP traps: https://github.com/soniah/gosnmp
Now, lets say I want to programmatically break out of the (taken from here):
err := tl.Listen("0.0.0.0:9162")
What are my best approaches to this?
I'm somewhat new to Golang and didnt find a way to break out of a goroutine that I have no way of modifying ("3rd party").
Thanks,
Short answer: You can't. There's no way to kill a goroutine (short of killing the entire program) from outside the goroutine.
Long answer: A goroutine can listen for some sort of "terminate" signal (via channels, signals, or any other mechanism). But ultimately, the goroutine must terminate from within.
Looking at the library in your example, it appears this functionality is not provided.
Standard https://golang.org/pkg/net/#Conn interface provides special methods SetDeadline (together with SetReadDeadline and SetWriteDeadline) to set a hard connection break time for staled connections. As I see in the source code:
type GoSNMP struct {
// Conn is net connection to use, typically established using GoSNMP.Connect()
Conn net.Conn
...
// Timeout is the timeout for the SNMP Query
Timeout time.Duration
...
net.Conn interface is exported - so you may try to get direct access to it to set up a deadline.
type TrapListener struct {
OnNewTrap func(s *SnmpPacket, u *net.UDPAddr)
Params *GoSNMP
...
}
In its turn TrapListener exports GoSNMP struct so you may have access to it. Try this:
tl := TrapListener{...}
tl.Params.Conn.SetDeadline(time.Now().Add(1*time.Second))
tl.Listen(...)
However this line disensures me - looks like it doesn't use stored connection and its options:
func (t *TrapListener) Listen(addr string) (err error) {
...
conn, err := net.ListenUDP("udp", udpAddr)
....
}
But you may try :)

Is it safe to hide sending to channel behind function call

I have a struct called Hub with a Run() method which is executed in its own goroutine. This method sequentially handles incoming messages. Messages arrive concurrently from multiple producers (separate goroutines). Of course I use a channel to accomplish this task. But now I want to hide the Hub behind an interface to be able to choose from its implementations. So, using a channel as a simple Hub's field isn't appropriate.
package main
import "fmt"
import "time"
type Hub struct {
msgs chan string
}
func (h *Hub) Run() {
for {
msg, hasMore := <- h.msgs
if !hasMore {
return
}
fmt.Println("hub: msg received", msg)
}
}
func (h *Hub) SendMsg(msg string) {
h.msgs <- msg
}
func send(h *Hub, prefix string) {
for i := 0; i < 5; i++ {
fmt.Println("main: sending msg")
h.SendMsg(fmt.Sprintf("%s %d", prefix, i))
}
}
func main() {
h := &Hub{make(chan string)}
go h.Run()
for i := 0; i < 10; i++ {
go send(h, fmt.Sprintf("msg sender #%d", i))
}
time.Sleep(time.Second)
}
So I've introduced Hub.SendMsg(msg string) function that just calls h.msgs <- msg and which I can add to the HubInterface. And as a Go-newbie I wonder, is it safe from the concurrency perspective? And if so - is it a common approach in Go?
Playground here.
Channel send semantics do not change when you move the send into a method. Andrew's answer points out that the channel needs to be created with make to send successfully, but that was always true, whether or not the send is inside a method.
If you are concerned about making sure callers can't accidentally wind up with invalid Hub instances with a nil channel, one approach is to make the struct type private (hub) and have a NewHub() function that returns a fully initialized hub wrapped in your interface type. Since the struct is private, code in other packages can't try to initialize it with an incomplete struct literal (or any struct literal).
That said, it's often possible to create invalid or nonsense values in Go and that's accepted: net.IP("HELLO THERE BOB") is valid syntax, or net.IP{}. So if you think it's better to expose your Hub type go ahead.
Easy answer
Yes
Better answer
No
Channels are great for emitting data from unknown go-routines. They do so safely, however I would recommend being careful with a few parts. In the listed example the channel is created with the construction of the struct by the consumer (and not not by a consumer).
Say the consumer creates the Hub like the following: &Hub{}. Perfectly valid... Apart from the fact that all the invokes of SendMsg() will block for forever. Luckily you placed those in their own go-routines. So you're still fine right? Wrong. You are now leaking go-routines. Seems fine... until you run this for a period of time. Go encourages you to have valid zero values. In this case &Hub{} is not valid.
Ensuring SendMsg() won't block could be achieved via a select{} however you then have to decide what to do when you encounter the default case (e.g. throw data away). The channel could block for more reasons than bad setup too. Say later you do more than simply print the data after reading from the channel. What if the read gets very slow, or blocks on IO. You then will start pushing back on the producers.
Ultimately, channels allow you to not think much about concurrency... However if this is something of high-throughput, then you have quite a bit to consider. If it is production code, then you need to understand that your API here involves SendMsg() blocking.

How to implement Memory Pooling in Golang

I implemented an HTTP server in Go.
For each request, I need to create hundreds of objects for a particular struct, and I have ~10 structs like that. So after the request is finished as per Go implementation it will be garbage collected.
So for each request this much amount of memory will be allocated and deallocated.
Instead I wanted to implement memory pooling to improve performance from allocation side as well as GC side also
In the beginning of request, I will take from pool and put them back after the request is served
From the pool implementation side
How to allocate and deallocate memory of a particular type of struct?
How keep track of information this memory got assigned and other is not?
Any other suggestions to improve performance in case of memory allocation and deallocation?
Note beforehand:
Many suggest to use sync.Pool which is a fast, good implementation for temporary objects. But note that sync.Pool does not guarantee that pooled objects are retained. Quoting from its doc:
Any item stored in the Pool may be removed automatically at any time without notification. If the Pool holds the only reference when this happens, the item might be deallocated.
So if you don't want your objects in the Pool to get garbage collected (which depending on your case might result in more allocations), the solution presented below is better, as values in the channel's buffer are not garbage collected. If your objects are really that big that memory pool is justified, the overhead of the pool-channel will be amortized.
Moreover, sync.Pool does not allow you to limit the number of pooled objects, while the presented solution below naturally does.
The simplest memory pool "implementation" is a buffered channel.
Let's say you want a memory pool of some big objects. Create a buffered channel holding pointers to values of such expensive objects, and whenever you need one, receive one from the pool (channel). When you're done using it, put it back to the pool (send on the channel). To avoid accidentally losing the objects (e.g. in case of a panic), use defer statement when putting them back.
Let's use this as the type of our big objects:
type BigObject struct {
Id int
Something string
}
Creating a pool is:
pool := make(chan *BigObject, 10)
The size of the pool is simply the size of the channel's buffer.
Filling the pool with pointers of expensive objects (this is optional, see notes at the end):
for i := 0; i < cap(pool); i++ {
bo := &BigObject{Id: i}
pool <- bo
}
Using the pool by many goroutines:
wg := sync.WaitGroup{}
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
bo := <-pool
defer func() { pool <- bo }()
fmt.Println("Using", bo.Id)
fmt.Println("Releasing", bo.Id)
}()
}
wg.Wait()
Try it on the Go Playground.
Note that this implementation blocks if all the "pooled" objects are in use. If you don't want this, you may use select to force creating new objects if all are in use:
var bo *BigObject
select {
case bo = <-pool: // Try to get one from the pool
default: // All in use, create a new, temporary:
bo = &BigObject{Id:-1}
}
And in this case you don't need to put it back into the pool. Or you may choose to try to put all back into the pool if there's room in the pool, without blocking, again with select:
select {
case pool <- bo: // Try to put back into the pool
default: // Pool is full, will be garbage collected
}
Notes:
Filling the pool prior is optional. If you use select to try to get / put back values from / to the pool, the pool may initially be empty.
You have to make sure you're not leaking information between requests, e.g. make sure you don't use fields and values in your shared objects that were set and belong to other requests.
This is the sync.Pool implementation mentioned by #JimB. Mind the usage of defer to return object to pool.
package main
import "sync"
type Something struct {
Name string
}
var pool = sync.Pool{
New: func() interface{} {
return &Something{}
},
}
func main() {
s := pool.Get().(*Something)
defer pool.Put(s)
s.Name = "hello"
// use the object
}

Using channels in Go created by a 'for' loop

Can channels created in a for loop be interchangeably used by subroutines running concurrently from that for loop?
Pseudocode is below:
for i := range Map {
channel := make(chan my_type, buff_size)
go subroutine(Map[i], channel)
}
func subroutine(name valueType, channel channelType) {
// Stuff here
}
Is there a way were subroutine(Map[0]) for example, could access another channel created during another iteration of the for loop, i.e., channel of subroutine(Map[1])?
Context: I'm currently working on a project where I have to simulate different populations of cells. Each cell has the ability to divide, differentiate, etc. To replicate the real system, the different populations have to run concurrently with one another. The issue is that I have to insert/remove a cell of a specific population type while working on a different population, this is where the channels come into play. I was thinking of running the populations concurrently each of them having an associated channel. And this is why I'm asking if we can use channels created in different for loop iterations.
Here is some of my code to support my context description with comments explaining the different elements. I've included channels, but I have no idea if it works. I'm hoping it helps with understanding what I'm trying to do:
func main() {
// Where envMap is a map[int]Population and Population is a struct
envMap := initialiseEnvironment(envSetupInfo)
// General simulation loop
for i := 0; i < 10; i++ {
// Loop to go through all envMap elements in parallel
for eachKey := range envMap {
channel := make(chan type)
go simulateEnv(envMap[eachKey])
}
}
}
func simulateEnv(cellPopulation Population, channel chan) {
// Each Population has a map[int]Cell where Cell is a struct with cell properties
cellMap := cellPopulation.cellMap
for eachCell := range cellMap {
go divisionTransition(eachCell, channel)
}
}
Assuming each element of the map is a struct, you could make a field to hold references to other channels. For example, if you wanted each element of your map to have a reference to the previous channel, you could do something like this:
// assumes that Map[whatever] is a struct with a "lastChan" field
var lastRef = chan my_type
for i := range Map {
channel := make(chan my_type, buff_size)
if(lastRef != nil){
Map[i].lastChan = lastRef
}
go subroutine(Map[i], channel)
lastRef = channel
}
func subroutine(name valueType, channel channelType) {
//stuff here can access the previous channel with name.lastChan
}
Depending on what you want to do and which channels you need access to, you may wish to play around with the looping or even do mutliple loops.

Resources