I know that, right now (and probably forever), we won't have static variables in Go... but is there a way to protect variables in some way?
import (
"net/http"
"net/http/cookiejar"
)
func funcThatDoesRequests(request Request) (response Response, e error){
static cookieJar, _ := cookiejar.New(nil)
static client := http.Client{ Jar: cookieJar }
response, e = client.Do(handshakeRequest)
return
}
I don't want the http client and its cookieJar floating around so other functions can do something with them. I need the cookieJar and client to only be accessible inside the funcThatDoesRequests. Is that possible?
Static variables (see static keyword in the pseudo code example) is a feature present in languages like C and PHP, to name some common languages.
Usually it's best not to worry about package-scoped globals since it's only code in your own package that can abuse them.
But if you really want, you can use a closure which is created when your package is loaded to generate the "static" variables.
func makeFunc() func(req Request)(Response, error) {
cookieJar, _ := cookiejar.New(nil)
client := http.Client{Jar: cookieJar}
return func(req Request)(Response, error) {
return client.Do(handshakeRequest)
}
}
var funcThatDoesRequests = makeFunc()
Now funcThatDoesRequests maintains client and cookieJar over multiple calls, but the names don't leak into the package.
One possibility would be to create a struct with your "private, static" variables and make your handler a method of that struct.
type privateData struct {
jar *cookiejar.Jar
client http.Client
}
func (r *privateData) Initialize() {
r.jar = cookiejar.New(nil)
r.client = http.Client{Jar: r.jar}
}
func (r *privateData) Do (request Request) (response Response, e error) {
/* Rest of the code goes here */
}
/* then, somewhere... */
var thing privateData
thing.Initialize()
/* then you can pass thing.Do where you would have passed funcThatDoesRequests */
Related
If I have a struct and some code that processes arrays of this struct, where would be the place to put this code?
struct Thing {
var id : String
let type : ThingType
}
things:[Thing]?
I have code to retrieve values from a server which returns an array of 100 Thing. Where should the code go?
I've currently defined it as a static function of the Struct but would like to follow a convention, if there is one.
A function that retrieves Thing instances from a server most certainly should not be a member of Thing.
It's best to make a new protocol that declares the function, like so:
protocol ThingProvider {
func fetchThings() -> [Thing]
}
and a conforming type:
class DataBaseThingProvider: ThingProvider {
init() {
// open database connection
}
deinit() {
// close database connection
}
func fetchThings() -> [Thing] {
// fetch Things from database
}
}
This way, you can change the provider you use (Firebase, Parse, SQLite, CoreData, JSON, CSV, whatever.) by just swapping out the concrete provider class you use, and all other code can stay the same.
It also makes your code much more testable, because you can easily construct a mock provider, which decouples your tests from your production backend.
class MockThingProvider: ThingProvider {
func fetchThings() -> [Thing] {
return [
Thing(id: "MockThing1", type: thingType1),
Thing(id: "MockThing2", type: thingType2),
Thing(id: "MockThing3", type: thingType3)
]
}
}
I have recently started programming with Go on Google App Engine and I have run into a road block. I come from Java land so it's been a slight struggle to adapt to Go.
I want to have a method that allows me to pass in a pointer to a slice that I can then pass into the datastore.GetAll call to retrieve the results. I then want to iterate through the results and use an assertion to cast as a specific interface (Queryable) in order to call a method Map().
Initially, I had this functioning properly:
func (s ProjectService) RunQuery(context context.Context, q *datastore.Query, projects *[]Project) error {
keys, err := q.GetAll(context, projects)
if err != nil {
return err
}
for i, key := range keys {
(*projects)[i].Id = key.Encode()
(*projects)[i].CompanyId = (*projects)[i].Company.Encode()
}
return nil
}
I want to have a more generic method that can be applied to any entity that implements a Queryable interface. The idea is to have a hook that allows me to perform some post processing after retrieving the results. I've looked into the ProperyLoadSaver interface however I have no access to the actual key that is associated to the entity. I would like to store the string representation of the datastore.Key in the entity.
This is the Queryable interface:
type Queryable interface {
Map(*datastore.Key) error
}
Here's an example entity that I am persisting to the GAE store:
type Camera struct {
Id string `datastore:"-"`
ProjectId string `datastore:"-"`
Name string
Project *datastore.Key `json:"-"`
Active bool
Timestamp Timestamp
}
// Implement Queryable interface. Let me perform any additional mapping
func (c *Camera) Map(key *datastore.Key) error {
c.Name = "Maybe do other things here"
c.Id = key.Encode()
return nil
}
The idea is to have something like the snippet below.
func (c Crud) RunQuery(context context.Context, q *datastore.Query, entities interface{}) error {
keys, err := q.GetAll(context, entities)
v := reflect.ValueOf(entities)
dv := v.Elem()
for i, key := range keys {
// I left this in to show that this worked however this won't let me enforce the interface contract
//dv.Index(i).FieldByName("Id").Set(reflect.ValueOf(key.Encode()))
entity := dv.Index(i).Interface().(Queryable)
entity.Map(key)
}
return err
}
However, when this executes, it panics with the following:
PANIC: interface conversion: entity.Camera is not entity.Queryable: missing method Map goroutine 9 [running]:
Just as a note, I realize the appropriate way to perform an assertion is to do if as, ok := elem.(Type); ok {} but I just wanted to see what the error was
I am guessing I am getting this error because I have defined my parameter with a pointer receiver func (c *Camera) Map(key *datastore.Key) error and not func (c Camera) Map(key *datastore.Key) error However, I want to modify the actual value.
Where am I going wrong with this? Is my Java-ness showing?
Being that I am very new to Go, I may be approaching this completely wrong.
Because the method is on a pointer receiver (as it should be), use the address of the slice element:
entity := dv.Index(i).Addr().Interface().(Queryable)
An alternative approach is to use a slice of pointers for the result:
var result []*Camera
err := c.RunQuery(ctx, q, &result)
The code can be written to work with both []Camera or []*Camera as follows:
var queryableType = reflect.TypeOf((*Queryable)(nil)).Elem()
needAddr := !dv.Type().Implements(queryableType)
...
var entity Queryable
if needAddr {
entity = dv.Index(i).Addr().Interface().(Queryable)
} else {
entity = dv.Index(i).Interface().(Queryable)
}
Sorry for a bit dummy questions, but I'm kinda stuck.
So, I'm implementing wrapper above database driver for my application, and I need to keep it as portable as possible.
I came to decision that interfaces are perfect match for this task. So, I have my database struct with some variables and app-specific methods, and two interface functions:
query(request string) error
flush() int? string?? struct?? slice????, error
Now you probably got the main question. How do I do return data that type "flush()" doesn't know? Can I return it by interface, and if I can, how to work with that?
Second question is pretty basic, but still it isn't clear to me.
So, I have this database struct with two methods designed to be implemented by package user to use db driver he want.
Ho do I write it and how future implementation will look (there is an example on tour of go, but it's about interface for different structs with similar methods)
Hope you'll help me find an understanding :)
Yes, flush can just have the signiture;
flush() interface{}, error
How do you implement? Something like this with reasonable method bodies should do it for you;
type MyDbDriver struct {
//fields
}
func (d *MyDbDriver) query(request string) error {
return nil
}
func (d *MyDbDriver) flush() interface{}, error {
return nil, nil
}
In Go all interface implementations are implicit, meaning, if your type has methods that match the interfaces signature, then you've implemented it. No need for something like public class MyType: IMyInterface, IThisIsntCSharp. Note that in the example above *MyDbDriver has implemented your interface but MyDbDriver has not.
Edit: below a some pseudo calling code;
e := driver.query("select * from thatTable where ThatProperty = 'ThatValue'")
if e != nil {
return nil, e
}
i, err := driver.flush()
if err != nil {
return nil, err
}
MyConcreteInstance := i.(MyConcreteType)
// note that this will panic if the type of i is not MyConcreteType
// that can be avoided with the familiar object, err calling syntax
MyConcreteIntance, ok := i.(MyConcreteType)
if !ok {
// the type of i was not MyConcreteType :\
}
I have implemented the levigo wrapper in my project so I can use LevelDB. The declaration is fairly boilerplate, like so:
func NewLeveldbStorage(dbPath string) *leveldbStorage {
opts := levigo.NewOptions()
opts.SetCache(levigo.NewLRUCache(3<<30))
opts.SetCreateIfMissing(true)
log.Debugf("Entering Open")
db, err := levigo.Open(dbPath, opts); if err != nil {
log.Fatal("BOOM %v", err)
}
log.Debugf("Finished calling open")
opts.Close()
return &leveldbStorage{db:db}
}
Here is the struct returned:
type leveldbStorage struct {
db *levigo.DB
}
I then made a few simple GET and STORE commands on the struct that essentially just use s.db.Get and s.db.Put. This works fine in my tests, but when I run the following benchmark:
func BenchmarkLeviDbGet(b *testing.B) {
s := storage.NewLeveldbStorage("/path/to/db")
value := "value"
uid,_ := s.Store(value)
b.ResetTimer()
for i := 0; i < b.N; i++ {
s.Get(uid)
}
This benchmark, when run, returns:
2014/10/12 21:17:09 BOOM %vIO error: lock /path/to/db/LOCK: already held by process
Is there an appropriate way to use levigo/leveldb to enable multithreaded reading? What about writing? I would not be surprised if multithreaded writing is not possible, but multithreaded reading seems like it should be. What am I doing wrong here?
You either need to close the database file or use a global instance to it, you can't open the file multiple times, you can however access the same instance from multiple goroutines.
Is there a Go analogue to Python/Java's async datastore APIs? Or can one just use the normal API with the go keyword?
There is no Go equivalent to the Python or Java asynchronous APIs for any AppEngine service. In fact, the Go standard library has nothing in the standard asynchronous style either. The reason is that in Go, you write functions using a blocking style and compose them using some basic concurrency primitives based on need. While you cannot just tack go at the beginning of a dastore.Get call, it is still relatively straightforward. Consider the following, contrived example:
func loadUser(ctx appengine.Context, name strings) (*User, err) {
var u User
var entries []*Entry
done := make(chan error)
go func() {
// Load the main features of the User
key := datastore.NewKey(ctx, "user", name, 0, nil)
done <- datastore.Get(ctx, key)
}()
go func() {
// Load the entries associated with the user
q := datastore.NewQuery("entries").Filter("user", name)
keys, err := q.GetAll(ctx, &entries)
for i, k := range keys {
entries[i].key = k
}
done <- err
}()
success := true
// Wait for the queries to finish in parallel
for i := 0; i < 2 /* count the funcs above */; i++ {
if err := <-done; err != nil {
ctx.Errorf("loaduser: %s", err)
success = false
}
}
if !success {
return
}
// maybe more stuff here
}
This same approach can be used in pretty much any context in which you need to run more than one thing that might take awhile at the same time, whether it's a datastore call, urlfetch, file load, etc.
There is no explicit API for async in Go. You should use go routines instead. I haven't seen any source on this, but I suspect the async API isn't there because of how easy it is to use go routines.