In Go one can create one-way channels. It's a very convenient feature in case of one want to restrict a set of operations available on the given channel. However, as far as I can see, this feature is useful only for function's arguments and variable's type specification, while creating one-way channels via make looks strange for me. I've read this question, but it's not about creating read (or write)-only channels in Go, it's about usage in general. So, my question is about use cases of the next code:
writeOnly := make(chan<- string)
readOnly := make(<-chan string)
Theoretically you can use write only channels for unit testing to ensure for example that your code is not writing more than specific number of times to a channel.
Something like this: http://play.golang.org/p/_TPtvBa1OQ
package main
import (
"fmt"
)
func MyCode(someChannel chan<- string) {
someChannel <- "test1"
fmt.Println("1")
someChannel <- "test2"
fmt.Println("2")
someChannel <- "test3"
fmt.Println("3")
}
func main() {
writeOnly := make(chan<- string, 2) // Make sure the code is writing to channel jsut 2 times
MyCode(writeOnly)
}
But that would be pretty silly technique for unit testing. You're better to create a buffered channel and check its contents.
One of the main reason that people use types (especially in Go) is as a form of documentation. Being able to show that a channel is read-only or write-only, can help the consumer of the API have a better idea of what is going on.
Related
I have this:
var wd, _ = os.Getwd()
var advanceAgreementTemplateBytes, _ = ioutil.ReadFile(path.Join(wd, "/docs/templates/advance-agreement.template"))
var advanceAgreementTemplate = string(advanceAgreementTemplateBytes)
var t, _ = template.New("advance-agreement").Parse(string(advanceAgreementTemplate))
func sendAdvanceEmail(user *common.User, amount *apd.Decimal, fee *apd.Decimal, created time.Time) {
// use variables `t`, `advanceAgreementTemplate` etc here
}
I want to be able to handle the errors in the cached variables instead of using _ instead of err. Is the only way to do this is to use func init()?
If you want to error-check these, use func init or just initialize them in main.
Not all calls have Must variants, and such variants don't make sense for all calls. Don't forget that the Go way is to do proper error checking. Having Must wrappers for all possible failing calls would encourage a bad programming style, where instead of handling and propagating errors, every error would crash by default.
It's very easy to write your own Must wrappers if all you need is to crash the program on error.
The benefit of writing your own Must wrapper is that you could provide a much better error message - another thing Go encourages. ioutil.ReadFile will just say "open /docs/templates/advance-agreement.template: No such file or directory".
I'm interested in using a Go package that uses a global variable which, for my application, is a key "variable". Each time I call this package, I want to set that variable (it's exported). And I'm calling it from various Go routines. Is there a recommended strategy for sequencing/syncing my calls to that package so that my code isn't colliding on that global variable?
Here's an example:
package main
import (
"fmt"
"sync"
"time"
"github.com/jameshaskell/_sketches/globalvars/testlib"
)
var wg sync.WaitGroup
func gr(i int) {
defer wg.Done()
testlib.GlobalVar = i
duration := time.Duration(i) * time.Millisecond
time.Sleep(duration)
fmt.Printf(" pause %d DONE\n", i)
fmt.Printf(" global var: %d should be: %d TestFunc: %s\n", testlib.GlobalVar, i, testlib.TestFunc())
}
func main() {
for i := 0; i <= 10; i += 1 {
wg.Add(1)
go gr(i)
}
wg.Wait()
}
The package I'm trying to access would be like:
package testlib
import "fmt"
var GlobalVar int
func TestFunc() string {
return fmt.Sprintf("GlobalVar: %d\n", GlobalVar)
}
NOTE: the package I'm hoping to use (having the global var) isn't mine...
Is this variable intended to be used this way? May be there’re some specific setters/getters for it? Does documentation have some info about?
I think code becomes very fragile because you do not control all accesses to the variable. You may serialize access from your code with a mutex. But another lib’s code doesn’t know about your it. Moreover it can change suddenly in new versions or bug fixes.
So I prefer:
To read about it in official docs
If documentation allows, and I can’t avoid to use it, protect access to the variable with sync/mutex/atomic/channel depending on a task.
Prepare tests to cover different cases with the variable
Run race condition detector as part of my CI tests.
You could use the atomic package, but beware the warning there:
These functions require great care to be used correctly. Except for
special, low-level applications, synchronization is better done with
channels or the facilities of the sync package. Share memory by
communicating; don't communicate by sharing memory.
Or you could use sync.Mutex to protect the variable but this would require wrapping it in a struct or an access function to properly control access.
There is a broader question though which you should attempt to answer - if you set this variable every time you access the package, why is it a package variable at all? Why not instead just pass it in to the function which needs it? Since it changes every time anyway, there's little point in a package variable quite apart from the synchronisation problems it poses.
Use the atomic package with the Value type
I'm trying to do something that seems like it should be trivial until I read up and now it seems like it should be really complex. ;-)
I've knocked up a test pattern to illustrate:
http://play.golang.org/p/Re88vJZvPT
At the most basic I'm trying to have a function that can read data from a channel and spit it out on another one. Easy. The test does this as long as you use the pusher function shown.
However the problem with this is that doing it this way I would need a different pusher function for each type of data I want to push through it.
Now I've done similar things in the past with an empty interface as nothing in the pusher code cares about what's in the data structure. What I can't figure out is when I'm dealing with channels of an un-cared-about data structure.
To illustrate the concept of what I'm trying to achieve please see the function pusher_naive_generic.
However that doesn't work either so more reading up implied the way to do it was making use of reflection and finally you see my pusher_reflect_generic function(obviously this won't achieve the same intended function as the others it's showing where I got to before getting stuck).
Which still fails because I can't get from an interface that contains a chan to the structure read from that chan.
Hopefully the code makes more sense of what I'm trying to achieve than my words actually do. I can make all of this work by explicitly coding for every type, but what I can't figure out how to do is code it for any future type.
If I have understood your question correctly, then this might be the solution:
http://play.golang.org/p/xiDO7xkoW4
func forwardChannel(i interface{}, o interface{}) {
it, ot := reflect.TypeOf(i), reflect.TypeOf(o)
if it != ot {
panic("forwardChannel: both arguments must be of the same type")
}
iv, ov := reflect.ValueOf(i), reflect.ValueOf(o)
for {
v, k := iv.Recv()
if !k {
break
}
ov.Send(v)
}
ov.Close()
}
Note that Recv, Send and Close panic if i and o are not channels.
I'm currently in the process of still learning go but I recently got to a point where in one of my tests I wanted to create a quick backup application that will reference a config file and switch what "plugin" to use for the backup. So what I got to at this point is to create (as example, written from my head and syntax may be incorrect):
type BackupStorage interface{
Put (d []byte) (n int, err Error)
Get (l []byte) (d []byte, err Error)
}
At this point I would assume I should use reflection to switch on the type and return the specific backup function, although that does not seem right.
The second alternative I came to was to still use my BackupStorage interface and create "plugin" packages to dictate which import will be used, but how do I switch that then based on a config file variable. And I'd like to do this because some stuff on one machine may backup only to s3 where as others may backup to both s3 and google drive etc.
With the basic example above what I have in mind is this:
Implement 2 BackupStorage "plugins" (Google Drive / S3) with the flexibility to add more at any time, but have my code be generic enough to execute on whatever storage backend is selected in config files.
As I mentioned above I'm still learning and any explanations would be appreciated or examples on how to accomplish this. I don't mind the "your doing it wrong" as long as there is a proper explanation on why it's wrong and how to do it right.
You have the right idea to start, implement everything you need via an interface, and then you can plug in any concrete backup "plugin" that implements that interface.
Once you can run your backup via an interface, you can simply assign an instance of the backend you want based on whatever conditions you set.
var storage Backupper
type Backupper interface {
Backup()
}
type GDrive struct {
config string
}
func (g *GDrive) Backup() {
fmt.Println("Doing backup to Google Drive")
}
func main() {
storage = &GDrive{}
storage.Backup()
}
Or with multiple options: http://play.golang.org/p/RlmXjf55Yh
Golang provides the file package to access Cloud Storage.
The package's Create function requires the io.WriteCloser interface. However, I have not found a single sample or documentation showing how to actually save a file to Cloud Storage.
Can anybody help? Is there a higher level implementation of io.WriteCloser that would allow us to store files in Cloud Storage? Any sample code?
We've obviously tried to Google it ourselves but found nothing and now hope for the community to help.
It's perhaps true than the behavior is not well defined in the documentation.
If you check the code: https://code.google.com/p/appengine-go/source/browse/appengine/file/write.go#133
In each call to Write the data is sent to the cloud (line 139). So you don't need to save. (You should close the file when you're done, through.)
Anyway, I'm confused with your wording: "The package's Create function requires the io.WriteCloser interface." That's not true. The package's Create functions returns a io.WriteCloser, that is, a thingy you can write to and close.
yourFile, _, err := Create(ctx, "filename", nil)
// Check err != nil here.
defer func() {
err := yourFile.Close()
// Check err != nil here.
}()
yourFile.Write([]byte("This will be sent to the file immediately."))
fmt.Fprintln(yourFile, "This too.")
io.Copy(yourFile, someReader)
This is how interfaces work in Go. They just provide you with a set of methods you can call, hiding the actual implementation from you; and, when you just depend on a particular interface instead of a particular implementation, you can combine in multiple ways, as fmt.Fprintln and io.Copy do.