1) How does golang solve visibility issue?
2) Is there any issues with below code?
package main
type Service struct {
stop bool
}
func (s *Service) Run() {
for !s.stop {
//Some logic
}
}
func (s *Service) Stop() {
s.stop = true
}
func main() {
s := &Service{}
go s.Run()
//Some logic
s.Stop()
}
I recommend to use context.WithCancel to stop goroutines in this case.
Related
Is there anything wrong with using methods as goroutines this way?
Do I need a mutex on data if Work() method only reads?
Is there a better pattern I can use to implement this kind of service.
type Worker struct {
data string
}
func (w *Worker) fetchData() {
for {
// sleep for defined period of time
// fetch the data
w.data = fetched_data
}
}
func (w *Worker) Work() {
go w.fetchData()
for {
// do some work that reads w.data
}
}
func main() {
worker := Worker{"data"}
worker.Work()
}
package main
import (
"fmt"
"sync"
"time"
)
func main() {
manager := NewPlatformManager()
pTrain := &PassengerTrain{mediator:manager}
mTrain := &MailTrain{mediator:manager}
pTrain.Arrive()
mTrain.Arrive()
pTrain.Depart()
//pTrain.Arrive()
//mTrain.Depart()
//time.Sleep(20000 * time.Millisecond)
}
/*
Mediator pattern
*/
type Train interface {
Arrive()
Depart()
PermitArrival()
}
type Mediator interface {
allowLanding(Train) bool
notifyFree()
}
type PassengerTrain struct {
mediator Mediator
}
func (t *PassengerTrain) Arrive() {
if !t.mediator.allowLanding(t) {
fmt.Println("Station Busy, passenger train")
} else {
fmt.Println("Landing on station, passenger train")
time.Sleep(3000 * time.Millisecond)
}
}
func (t *PassengerTrain) Depart() {
t.mediator.notifyFree()
fmt.Println("leaving station, passenger train")
}
func (t *PassengerTrain) PermitArrival() {
fmt.Println("Allowed to arrive, passenger train")
t.Arrive()
}
type MailTrain struct {
mediator Mediator
}
func (t *MailTrain) Arrive() {
if !t.mediator.allowLanding(t) {
fmt.Println("Station Busy, mail train")
} else {
fmt.Println("Landing on station, mail train")
time.Sleep(5000 * time.Millisecond)
}
}
func (t *MailTrain) Depart() {
t.mediator.notifyFree()
fmt.Println("leaving station, mail train")
}
func (t *MailTrain) PermitArrival() {
fmt.Println("Allowed to arrive, mail train")
t.Arrive()
}
type PlatformManager struct {
queue []Train
signal *sync.Mutex
isBlocked bool
}
func NewPlatformManager() Mediator {
instance := &PlatformManager{
queue: make([]Train,0),
signal: &sync.Mutex{},
isBlocked: false,
}
return instance
}
func (pm *PlatformManager) allowLanding(train Train) bool {
pm.signal.Lock()
defer pm.signal.Unlock()
if !pm.isBlocked {
pm.isBlocked = true
return true
}
pm.queue = append(pm.queue, train)
return false
}
func (pm *PlatformManager) notifyFree() {
pm.signal.Lock()
defer pm.signal.Unlock()
if pm.isBlocked {
pm.isBlocked = false
}
if len(pm.queue) > 0 {
nextTrain := pm.queue[0]
pm.queue = pm.queue[1:]
nextTrain.PermitArrival()
}
}
I get the error as below, I was expecting the code to go in a single flow son haven't defined any go routine either. the expected result should be passengerTrain arrives (waits 3 seconds)-> mailTrain is wanting to arrive (is asked to wait)-> passengerTrain leaves -> mailTrain is notified and it arrives and waits (5 seconds)
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_SemacquireMutex(0xc00002c00c, 0x486700, 0x1)
/usr/local/go-faketime/src/runtime/sema.go:71 +0x47
sync.(*Mutex).lockSlow(0xc00002c008)
/usr/local/go-faketime/src/sync/mutex.go:138 +0xfc
sync.(*Mutex).Lock(...)
/usr/local/go-faketime/src/sync/mutex.go:81
main.(*PlatformManager).allowLanding(0xc000060150, 0x4dd220, 0xc000010210, 0x0)
/tmp/sandbox325139098/prog.go:97 +0x17d
main.(*MailTrain).Arrive(0xc000010210)
/tmp/sandbox325139098/prog.go:63 +0x48
main.(*MailTrain).PermitArrival(0xc000010210)
/tmp/sandbox325139098/prog.go:78 +0x83
main.(*PlatformManager).notifyFree(0xc000060150)
/tmp/sandbox325139098/prog.go:117 +0xbb
main.(*PassengerTrain).Depart(0xc000010200)
/tmp/sandbox325139098/prog.go:49 +0x37
main.main()
/tmp/sandbox325139098/prog.go:15 +0x13b
I ran it in go playground https://play.golang.org/p/JO2mEQSk_kI
You are getting this error because func (pm *PlatformManager) notifyFree() creates a lock on pm.signal and then calls nextTrain.PermitArrival() which in turn tries to get a lock on pm.signal. Because of this layout of code, nextTrain.PermitArrival() will never get to lock pm.signal and hence the error on line no 97.
You can use go routines to implement this more elegantly. You can refer to this ping pong example to start with.
I am trying to write a program which exposes prometheus metrics.
It is a simple program, where I want to increment a counter for every time my "run" method is called on my struct.
import (
"log"
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
type myStruct struct {
errorCount prometheus.Counter
}
func (s myStruct) initialize() {
s.errorCount = prometheus.NewCounter(prometheus.CounterOpts{
Name: "my_counter",
Help: "sample prometheus counter",
})
}
func (s myStruct) run() {
s.errorCount.Add(1)
}
func main() {
s := new(myStruct)
s.initialize()
http.Handle("/metrics", promhttp.Handler())
go func() {
for {
s.run()
time.Sleep(time.Second)
}
}()
log.Fatal(http.ListenAndServe(":8080", nil))
}
Above code fails with a "Failed to continue - bad access" error, every time I try to increment the counter. i.e. at this line
s.errorCount.Inc()
I am unable to determine why the counter suddenly disappears from memory (if I'm understanding the error message correctly).
I am determine if i am missing something fundamental w.r.t. Go, or am I using the prometheus client library incorrectly.
In initialise() s is being passed by value which means that in main() s.errorCount is nil.
Just change the declaration of initialise (and run) to take a pointer.
func (s *myStruct) initialize() {
...
A few more suggestions you might like to try:
func init() {
go func() {
http.Handle("/metrics", promhttp.Handler())
log.Fatal(http.ListenAndServe(":8080", nil))
}()
}
type myStruct struct {
errorCount prometheus.Counter
}
func NewMyStruct() *myStruct {
return &myStruct {
errorCount: prometheus.NewCounter(prometheus.CounterOpts {
Name: "my_counter",
Help: "sample prometheus counter",
}),
}
}
func (s *myStruct) run() {
s.errorCount.Add(1)
}
func main() {
s := NewMyStruct()
go func() {
for {
s.run()
time.Sleep(time.Second)
}
}()
// ... OR select{}
}
How to implement an abstract class in Go? As Go doesn't allow us to have fields in interfaces, that would be a stateless object. So, in other words, is it possible to have some kind of default implementation for a method in Go?
Consider an example:
type Daemon interface {
start(time.Duration)
doWork()
}
func (daemon *Daemon) start(duration time.Duration) {
ticker := time.NewTicker(duration)
// this will call daemon.doWork() periodically
go func() {
for {
<- ticker.C
daemon.doWork()
}
}()
}
type ConcreteDaemonA struct { foo int }
type ConcreteDaemonB struct { bar int }
func (daemon *ConcreteDaemonA) doWork() {
daemon.foo++
fmt.Println("A: ", daemon.foo)
}
func (daemon *ConcreteDaemonB) doWork() {
daemon.bar--
fmt.Println("B: ", daemon.bar)
}
func main() {
dA := new(ConcreteDaemonA)
dB := new(ConcreteDaemonB)
start(dA, 1 * time.Second)
start(dB, 5 * time.Second)
time.Sleep(100 * time.Second)
}
This won't compile as it's not possible to use interface as a receiver.
In fact, I have already answered my question (see the answer below). However, is it an idiomatic way to implement such logic? Are there any reasons not to have a default implementation besides language's simplicity?
The other answers provide an alternative to your problem, however they proposed solution without using abstract classes/struct, and I guess if you were interested in using abstract class like solution, here is very precise solution to your problem:
Go plaground
package main
import (
"fmt"
"time"
)
type Daemon interface {
start(time.Duration)
doWork()
}
type AbstractDaemon struct {
Daemon
}
func (a *AbstractDaemon) start(duration time.Duration) {
ticker := time.NewTicker(duration)
// this will call daemon.doWork() periodically
go func() {
for {
<- ticker.C
a.doWork()
}
}()
}
type ConcreteDaemonA struct {
*AbstractDaemon
foo int
}
func newConcreteDaemonA() *ConcreteDaemonA {
a:=&AbstractDaemon{}
r:=&ConcreteDaemonA{a, 0}
a.Daemon = r
return r
}
type ConcreteDaemonB struct {
*AbstractDaemon
bar int
}
func newConcreteDaemonB() *ConcreteDaemonB {
a:=&AbstractDaemon{}
r:=&ConcreteDaemonB{a, 0}
a.Daemon = r
return r
}
func (a *ConcreteDaemonA) doWork() {
a.foo++
fmt.Println("A: ", a.foo)
}
func (b *ConcreteDaemonB) doWork() {
b.bar--
fmt.Println("B: ", b.bar)
}
func main() {
var dA Daemon = newConcreteDaemonA()
var dB Daemon = newConcreteDaemonB()
dA.start(1 * time.Second)
dB.start(5 * time.Second)
time.Sleep(100 * time.Second)
}
If this is still not obvious how to use abstract classes/multi-inheritance in go-lang here is the post with comprehensive details. Abstract Classes In Go
If you want to provide a "default" implementation (for Daemon.start()), that is not the characteristic of an interface (at least not in Go). That is a characteristic of a concrete (non-interface) type.
So Daemon in your case should be a concrete type, conveniently a struct since you want it to have fields. And the task to be done can be either a value of an interface type, or in a simple case just a function value (a simple case means it would only have one method).
With interface type
Try the complete app on the Go Playground.
type Task interface {
doWork()
}
type Daemon struct {
task Task
}
func (d *Daemon) start(t time.Duration) {
ticker := time.NewTicker(t)
// this will call task.doWork() periodically
go func() {
for {
<-ticker.C
d.task.doWork()
}
}()
}
type MyTask struct{}
func (m MyTask) doWork() {
fmt.Println("Doing my work")
}
func main() {
d := Daemon{task: MyTask{}}
d.start(time.Millisecond*300)
time.Sleep(time.Second * 2)
}
With a function value
In this simple case this one is shorter. Try it on the Go Playground.
type Daemon struct {
task func()
}
func (d *Daemon) start(t time.Duration) {
ticker := time.NewTicker(t)
// this will call task() periodically
go func() {
for {
<-ticker.C
d.task()
}
}()
}
func main() {
d := Daemon{task: func() {
fmt.Println("Doing my work")
}}
d.start(time.Millisecond * 300)
time.Sleep(time.Second * 2)
}
An easy solution is to move daemon *Daemon to the argument list (thus removing start(...) from the interface):
type Daemon interface {
// start(time.Duration)
doWork()
}
func start(daemon Daemon, duration time.Duration) { ... }
func main() {
...
start(dA, 1 * time.Second)
start(dB, 5 * time.Second)
...
}
You can implement abstract class in go.
The definition:
type abstractObject interface{
print()
}
type object struct{
a int
abstractObject
}
Now object is an abstract class, like java's.
You can inherit it and use its members:
type concreteObject struct{
*object
}
(o *concreteObject) print() {
fmt.Println(o.a)
}
func newConcreteObject(o *object) {
obj := &concreteObject{object: o}
o.abstractObject = obj // all magics are in this statement.
}
And use the object with concreteObject's methods:
o := &object{}
newConcereteObject(o)
o.print()
And cast abstract object to concrete object:
concObj := o.abstractObject.(*concreteObject)
Just like other OOP languages.
The solution by Max Malysh would work in some cases if you don't need a factory. However the solution given by Adrian Witas could cause cyclic dependencies issues.
This is the way I achieved implementing an abstract class the easy way respecting cyclic dependencies and good factory patterns.
Let us assume we have the following package structure for our component
component
base
types.go
abstract.go
impl1
impl.go
impl2
impl.go
types.go
factory.go
Define the definition of the component, in this example it will be defined here:
component/types.go
package component
type IComponent interface{
B() int
A() int
Sum() int
Average() int
}
Now let's assume we want to create an abstract class that implements Sum and Average only, but in this abstract implementation we would like to have access to use the values returned by the implemented A and B
To achieve this, we should define another interface for the abstract members of the abstract implementation
component/base/types.go
package base
type IAbstractComponentMembers {
A() int
B() int
}
And then we can proceed to implement the abstract "class"
component/base/abstract.go
package base
type AbstractComponent struct {
IAbstractComponentsMember
}
func (a *AbstractComponent) Sum() int {
return a.A() + a.B()
}
func (a *AbstractComponent) Average() int {
return a.Sum() / 2
}
And now we proceed to the implementations
component/impl1/impl.go // Asume something similar for impl2
package impl1
type ComponentImpl1 struct {
base.AbstractComponent
}
func (c *ComponentImpl1) A() int {
return 2
}
func (c *ComponentImpl1) A() int {
return 4
}
// Here is how we would build this component
func New() *ComponentImpl1 {
impl1 := &ComponentImpl1{}
abs:=&base.AbstractComponent{
IAbstractComponentsMember: impl1,
}
impl1.AbstractComponent = abs
return impl1
}
The reason we use a separate interface for this instead of using Adrian Witas example, is because if we use the same interface in this case, if we import the base package in impl* to use the abstract "class" and also we import the impl* packages in the components package, so the factory can register them, we'll find a circular reference.
So we could have a factory implementation like this
component/factory.go
package component
// Default component implementation to use
const defaultName = "impl1"
var instance *Factory
type Factory struct {
// Map of constructors for the components
ctors map[string]func() IComponent
}
func (f *factory) New() IComponent {
ret, _ := f.Create(defaultName)
return ret
}
func (f *factory) Create(name string) (IComponent, error) {
ctor, ok := f.ctors[name]
if !ok {
return nil, errors.New("component not found")
}
return ctor(), nil
}
func (f *factory) Register(name string, constructor func() IComponent) {
f.ctors[name] = constructor
}
func Factory() *Factory {
if instance == nil {
instance = &factory{ctors: map[string]func() IComponent{}}
}
return instance
}
// Here we register the implementations in the factory
func init() {
Factory().Register("impl1", func() IComponent { return impl1.New() })
Factory().Register("impl2", func() IComponent { return impl2.New() })
}
The functionality of abstract class has below requirements
1. It should not be possible to create direct instance of abstract class
2. It should provide default fields and methods.
A combination of interface and struct can be used to fulfill above two requirements. For example we can see below
package main
import "fmt"
//Abstract Interface
type iAlpha interface {
work()
common(iAlpha)
}
//Abstract Concrete Type
type alpha struct {
name string
}
func (a *alpha) common(i iAlpha) {
fmt.Println("common called")
i.work()
}
//Implementing Type
type beta struct {
alpha
}
func (b *beta) work() {
fmt.Println("work called")
fmt.Printf("Name is %s\n", b.name)
}
func main() {
a := alpha{name: "test"}
b := &beta{alpha: a}
b.common(b)
}
Output:
common called
work called
Name is test
One important point to mention here is that all default method should have iAlpha as first argument, and if default method needs to call any unimplemented method they they will call on this interface. This is same as we did in common method above - i.work().
Source: https://golangbyexample.com/go-abstract-class/
Suppose I have the following struct:
package manager
type Manager struct {
strings []string
}
func (m *Manager) AddString(s string) {
m.strings = append(m.strings, s)
}
func (m *Manager) RemoveString(s string) {
for i, str := range m.strings {
if str == s {
m.strings = append(m.strings[:i], m.strings[i+1:]...)
}
}
}
This pattern is not thread safe, so the following test fails due to some race condition (array index out of bounds):
func TestManagerConcurrently(t *testing.T) {
m := &manager.Manager{}
wg := sync.WaitGroup{}
for i:=0; i<100; i++ {
wg.Add(1)
go func () {
m.AddString("a")
m.AddString("b")
m.AddString("c")
m.RemoveString("b")
wg.Done()
} ()
}
wg.Wait()
fmt.Println(m)
}
I'm new to Go, and from googling around I suppose I should use channels (?). So one way to make this concurrent would be like this:
type ManagerA struct {
Manager
addStringChan chan string
removeStringChan chan string
}
func NewManagerA() *ManagerA {
ma := &ManagerA{
addStringChan: make(chan string),
removeStringChan: make(chan string),
}
go func () {
for {
select {
case msg := <-ma.addStringChan:
ma.AddString(msg)
case msg := <-ma.removeStringChan:
ma.RemoveString(msg)
}
}
}()
return ma
}
func (m* ManagerA) AddStringA(s string) {
m.addStringChan <- s
}
func (m* ManagerA) RemoveStringA(s string) {
m.removeStringChan <- s
}
I would like to expose an API similar to the non-concurrent example, hence AddStringA, RemoveStringA.
This seems to work as expected concurrently (although I guess the inner goroutine should also exit at some point). My problem with this is that there is a lot of extra boilerplate:
need to define & initialize channels
define inner goroutine loop with select
map functions to channel calls
It seems a bit much to me. Is there a way to simplify this (refactor / syntax / library)?
I think the best way to implement this would be to use a Mutex instead? But is it still possible to simplify this sort of boilerplate?
Using a mutex would be perfectly idiomatic like this:
type Manager struct {
mu sync.Mutex
strings []string
}
func (m *Manager) AddString(s string) {
m.mu.Lock()
m.strings = append(m.strings, s)
m.mu.Unlock()
}
func (m *Manager) RemoveString(s string) {
m.mu.Lock()
for i, str := range m.strings {
if str == s {
m.strings = append(m.strings[:i], m.strings[i+1:]...)
}
}
m.mu.Unlock()
}
You could do this with channels, but as you noted it is a lot of extra work for not much gain. Just use a mutex is my advice!
If you simply need to make the access to the struct thread-safe, use mutex:
type Manager struct {
sync.Mutex
data []string
}
func (m *Manager) AddString(s string) {
m.Lock()
m.strings = append(m.strings, s)
m.Unlock()
}