I would like to override below method(in request.go) to apply escape string (eg: template.HTMLEscapeString(r.FormValue("some_param")).
I want to override because I do not want to escape on every FormValue calling.
Is there a way to do so?
func (r *Request) FormValue(key string) string{
if r.Form == nil {
r.ParseMultipartForm(defaultMaxMemory)
}
if vs := r.Form[key]; len(vs) > 0 {
return vs[0]
}
return ""
}
You can't override anything in Go.
The simplest solution here is to define a small helper function along the lines of:
func EscapeFormValue(req *http.Request, key string) string {
return template.HTMLEscapeString(req.FormValue(key))
}
However, if you really want a custom struct with the same method, you can use embedding to wrap the http.Request and use the new wrapped type:
type newReq struct {
*http.Request
}
func (n *newReq) FormValue(key string) string {
return fmt.Sprintf("value: %s", n.Request.FormValue(key))
}
func main() {
req := &http.Request{Method: "GET"}
req.URL, _ = url.Parse("http://www.google.com/search?q=foo&q=bar")
n := newReq{req}
fmt.Println(n.FormValue("q"))
}
This outputs:
value: foo
Note that this only works because we are using newReq itself. Anything (including the http package) operating on a http.Request will want the embedded struct and will not see newReq.FormValue. This is what makes it different from overriding.
Related
I'm looking for an appropriate way to inject dependencies.
Say I have this code where the FancyWrite and FancyRead functions have a dependency on the WriteToFile and ReadFromFile functions. Since these have side effects I'd like to be able to inject them so I can replace them in tests.
package main
func main() {
FancyWrite()
FancyRead()
}
////////////////
func FancyWrite() {
WriteToFile([]byte("content..."))
}
func FancyRead() {
ReadFromFile("/path/to/file")
}
////////////////
func WriteToFile(content []byte) (bool, error) {
return true, nil
}
func ReadFromFile(file string) ([]byte, error) {
return []byte{}, nil
}
One thing I tried is just put them as parameters into the functions:
package main
func main() {
FancyWrite(WriteToFile)
FancyRead(ReadFromFile)
}
////////////////
func FancyWrite(writeToFile func(content []byte) (bool, error)) {
writeToFile([]byte("content..."))
}
func FancyRead(readFromFile func(file string) ([]byte, error)) {
readFromFile("/path/to/file")
}
////////////////
func WriteToFile(content []byte) (bool, error) {
return true, nil
}
func ReadFromFile(file string) ([]byte, error) {
return []byte{}, nil
}
So, this actually works great, but I could see this becoming harder to maintain for more dependencies. I also tried a factory pattern like the following so that the main function doesn't have to concern itself with building the FancyWrite function. But, the syntax is getting a little hard to read and with even more functions would be hard to maintain.
func FancyWriteFactory(writeToFile func(content []byte) (bool, error)) func() {
return func() {
FancyWrite(writeToFile)
}
}
So next I tried housing the functions as methods in a struct:
package main
func main() {
dfu := DefaultFileUtil{}
ffm := FancyFileModule{
FileUtil: &dfu,
}
ffm.FancyWrite()
ffm.FancyRead()
}
////////////////
type FileUtil interface {
WriteToFile(content []byte) (bool, error)
ReadFromFile(file string) ([]byte, error)
}
type FancyFileModule struct {
FileUtil
}
func (fm *FancyFileModule) FancyWrite() {
fm.FileUtil.WriteToFile([]byte("content..."))
}
func (fm *FancyFileModule) FancyRead() {
fm.FileUtil.ReadFromFile("/path/to/file")
}
////////////////
type DefaultFileUtil struct{}
func (fu *DefaultFileUtil) WriteToFile(content []byte) (bool, error) {
return true, nil
}
func (fu *DefaultFileUtil) ReadFromFile(file string) ([]byte, error) {
return []byte{}, nil
}
Now, this actually works well and is cleaner. However, I'm worried I am just shoehorning my functions as methods now and something just felt odd about that. I guess I can reason about it because structs are good when you have some state, and I guess I can count the dependencies as state?
Those are the things I tried. So my question is, what is the proper way to do dependency injection in this case when the only reason to put functions as methods is to make them be a collection of dependencies elsewhere?
Thanks!
The simple answer is that you cannot cleanly use dependency injection with functions, only with methods. Technically, you could make the functions global vars instead (ex. var WriteToFile = func(content []byte) (bool, error) { [...] }), but this is rather brittle code.
The more proper solution, from an idiomatic perspective, is to make any behavior you want to replace, inject, or wrap into a method that is then wrapped in an interface.
For example:
type (
FancyReadWriter interface {
FancyWrite()
FancyRead()
}
fancyReadWriter struct {
w Writer
r Reader
}
Writer interface {
Write([]byte) (bool, error)
}
Reader interface {
Read() ([]byte, error)
}
fileWriter struct {
path string
// or f *os.File
}
fileReader struct {
path string
// or f *os.File
}
)
func (w fileWriter) Write([]byte) (bool, error) {
// Write to the file
return true, nil
}
func (r fileReader) Read() ([]byte, error) {
// Read from the file
return nil, nil
}
func (f fancyReadWriter) FancyWrite() {
// I like to be explicit when I'm ignoring return values,
// hence the underscores.
_, _ = f.w.Write([]byte("some content..."))
}
func (f fancyReadWriter) FancyRead() {
_, _ = f.r.Read()
}
func NewFancyReadWriter(w Writer, r Reader) FancyReadWriter {
// NOTE: Returning a pointer to the struct type, but it is actually
// returned as an interface instead, abstracting the underlying
// implementation.
return &fancyReadWriter{
w: w,
r: r,
}
}
func NewFileReader(path string) Reader {
// Same here, returning a pointer to the struct as the interface
return &fileReader {
path: path
}
}
func NewFileWriter(path string) Writer {
// Same here, returning a pointer to the struct as the interface
return &fileWriter {
path: path
}
}
func Main() {
w := NewFileWriter("/var/some/path")
r := NewFileReader("/var/some/other/path")
f := NewFancyReadWriter(w, r)
f.FancyWrite()
f.FancyRead()
}
And then in the test file (or wherever you want to do the dependency injection):
type MockReader struct {}
func (m MockReader) Read() ([]byte, error) {
return nil, fmt.Errorf("test error 1")
}
type MockWriter struct {}
func (m MockWriter) Write([]byte) (bool, error) {
return false, fmt.Errorf("test error 2")
}
func TestFancyReadWriter(t *testing.T) {
var w MockWriter
var r MockReader
f := NewFancyReadWriter(w, r)
// Now the methods on f will call the mock methods instead
f.FancyWrite()
f.FancyRead()
}
You could then go a step further and make the mock or injection framework functional and thus flexible. This is my preferred style for mocks for tests, actually, as it lets me define the behavior of the mocked dependency within the test using that behavior. Example:
type MockReader struct {
Readfunc func() ([]byte, error)
ReadCalled int
}
func (m *MockReader) Read() (ret1 []byte, ret2 error) {
m.ReadCalled++
if m.Readfunc != nil {
// Be *very* careful that you don't just call m.Read() here.
// That would result in an infinite recursion.
ret1, ret2 = m.Readfunc()
}
// if Readfunc == nil, this just returns the zero values
return
}
type MockWriter struct {
Writefunc func([]byte) (bool, error)
WriteCalled int
}
func (m MockWriter) Write(arg1 []byte) (ret1 bool, ret2 error) {
m.WriteCalled++
if m.Writefunc != nil {
ret1, ret2 = m.Writefunc(arg1)
}
// Same here, zero values if the func is nil
return
}
func TestFancyReadWriter(t *testing.T) {
var w MockWriter
var r MockReader
// Note that these definitions are optional. If you don't provide a
// definition, the mock will just return the zero values for the
// return types, so you only need to define these functions if you want
// custom behavior, like different returns or test assertions.
w.Writefunc = func(d []byte) (bool, error) {
// Whatever tests you want, like assertions on the input or w/e
// Then whatever returns you want to test how the caller handles it.
return false, nil
}
r.Readfunc = func() ([]byte, error) {
return nil, nil
}
// Since the mocks now define the methods as *pointer* receiver methods,
// so the mock can keep track of the number of calls, we have to pass in
// the address of the mocks rather than the mocks as struct values.
f := NewFancyReadWriter(&w, &r)
// Now the methods on f will call the mock methods instead
f.FancyWrite()
f.FancyRead()
// Now you have a simple way to assert that the calls happened:
if w.WriteCalled < 1 {
t.Fail("Missing expected call to Writer.Write().")
}
if r.ReadCalled < 1 {
t.Fail("Missing expected call to Reader.Read().")
}
}
Since all of the types involved here (the Reader, Writer, and the FancyReadWriter) are all handed around as interfaces rather than concrete types, it also becomes trivial to wrap them with middleware or similar (ex. logging, metrics/tracing, timeout aborts, etc).
This is hands down the most power strength of Go's interface system. Start thinking of types as bags of behavior, attach your behavior to types that can hold them, and pass all behavior types around as interfaces rather than concrete structs (data structs that are just used to organize specific bits of data are perfectly fine without interfaces, else you have to define Getters and Setters for everything and it's a real chore without much benefit). This lets you isolate, wrap, or entirely replace any particular bit of behavior you want at any time.
I'm writing a package which needs to pass an instance of a *gorequest.SuperAgent to a method in a subpackage
// main.go
func main() {
req := gorequest.New()
result := subpackage.Method(req)
fmt.Println(result)
}
// subpackage.go
func Method(req *gorequest.SuperAgent) string {
req.Get("http://www.foo.com").Set("bar", "baz")
_, body, _ := req.End()
return body
}
I keep going in circles trying to write an interface for the gorequest superagent so I can properly isolate and test my subpackage methods with a stub of gorequest.
type Getter Interface {
Get(url string) Getter
// In the previous Method, Get() returns a *gorequest.SuperAgent
// which allows chaining of methods
// Here I tried returning the interface itself
// But I get a 'wrong type for Get method' error when passing a gorequest instance
// have Get(string) *gorequest.SuperAgent
// want Get(string) Getter
End(callback ...func(response *gorequest.Response, body string, errs []error)) (*gorequest.Response, string, []error)
// I have no idea how to handle the param and returned *gorequest.Response here
// Put another interface ?
// Tried replacing it with *http.Response but not quite understanding it
}
func Method(req Getter) string {
...
}
So as you can see I'm tripping up on several points here and haven't been able to find a good source to learn from. Any pointers would be greatly appreciated
Besides defining the Getter interface you can also define a thin wrapper around *gorequest.SuperAgent that implements the Getter interface.
type saGetter struct {
sa *gorequest.SuperAgent
}
func (g *saGetter) Get(url string) Getter {
g.sa = g.sa.Get(url)
return g
}
func (g *saGetter) Set(param string, value string) Getter {
g.sa = g.sa.Set(param, value)
return g
}
func (g *saGetter) End(callback ...func(response *gorequest.Response, body string, errs []error)) (*gorequest.Response, string, []error) {
return g.sa.End(callback...)
}
Then with your Method defined as:
// subpackage.go
func Method(req Getter) string {
req.Get("http://www.foo.com").Set("bar", "baz")
_, body, _ := req.End()
return body
}
You can use the saGetter in main like so:
// main.go
func main() {
req := gorequest.New()
result := subpackage.Method(&saGetter{req})
fmt.Println(result)
}
Then mocking Getter for testing the Method implementation is easy.
That said, I agree with #JimB's comments that you probably don't need gorequest and using net/http is generally the better choice.
I'm wondering if it's possible to get the method fields from a typed function using reflection or by other means.
The problem that I'm trying to solve is that I have a method which accepts a function of specific type but I need to actually transport different types and based on the type provided to execute operations. I'm aware that I could use an interface{} value as receiver but I don't want to loose the type checking on the calling function ("GetIt")
package main
type ttp struct {
Coupons string
}
func (m ttp) GetIt(x string) {
if m.Coupons != "" {
print(m.Coupons)
}
}
func calculate(mth func(s string)){
//perform calculations and update the Coupon field
mth.Cupons = "one coupon" // is not working :(
// execute it again with the processed value
mth.GetIt() // is not working
}
func main() {
m := ttp{Coupons: "something"}
calculate(m.GetIt)
}
Play
well this does not answer your exact question but it should solve your problem and cleanup the logic: push the calculate method inside the type and use a interface
https://play.golang.org/p/On_AigRYW6
package main
import "fmt"
type Computer interface {
Compute(string)
}
type myp struct {
Coupons string
}
// myp implements Computer
func (m *myp) Compute(x string) {
m.GetIt(x)
fmt.Println("myp")
}
type ttp struct {
Various string
}
// ttp implements Computer
func (m *ttp) Compute(x string) {
m.GetIt(x)
fmt.Println("ttp")
}
func (m myp) GetIt(x string) {}
func (m ttp) GetIt(x string) {}
func main() {
m := &myp{Coupons: "something"}
t := &ttp{Various: "various stuff"}
var stuff = []Computer{m, t}
for _, c := range stuff {
c.Compute("s")
}
}
I understand that Go doesn't have traditional OOP concepts. However, I'd love to know whether there is a better way for designing a "constructor" as I've done it in my code snippet below:
type myOwnRouter struct {
}
func (mor *myOwnRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello from my own Router!")
}
func newMyOwnRouter() *myOwnRouter {
return &myOwnRouter{}
}
func init() {
http.Handle("/", newMyOwnRouter())
...
}
I basically would like to get rid of the "stand alone" newMyOwnRouter() function and have it as part of the struct itself, for example I'd like to be able to do something like:
http.Handle("/", myOwnRouter.Router)
Is that doable?
The defacto standard pattern is a function calle New
package matrix
function NewMatrix(rows, cols int) *matrix {
m := new(matrix)
m.rows = rows
m.cols = cols
m.elems = make([]float, rows*cols)
return m
}
Of course the construct function must be a Public one, to be called outside of the package.
More about constructor pattern here
In your case looks like you want a Sigleton package then this is the pattern:
package singleton
type myOwnRouter struct {
}
var instantiated *myOwnRouter = nil
func NewMyOwnRouter() * myOwnRouter {
if instantiated == nil {
instantiated = new(myOwnRouter);
}
return instantiated;
}
I tried doing this:
package main
import (
"fmt"
"strings"
)
type String string
func (s *String) tolower() String {
*s = String(strings.ToLower(string(*s)))
return *s
}
func (s *String) toupper() String {
*s = String(strings.ToUpper(string(*s)))
return *s
}
func main() {
var s String = "ASDF"
(s.tolower()).toupper() // this fails
// s.toupper();s.tolower(); // this works
// s.tolower().toupper() // this fails too
fmt.Println(s)
}
But I got these errors:
prog.go:30: cannot call pointer method on s.tolower()
prog.go:30: cannot take the address of s.tolower()
Program exited.
Why can't I make this chain work?
This works:
package main
import (
"fmt"
"strings"
)
type String string
func (s *String) tolower() *String {
*s = String(strings.ToLower(string(*s)))
return s
}
func (s *String) toupper() *String {
*s = String(strings.ToUpper(string(*s)))
return s
}
func main() {
var s String = "ASDF"
(s.tolower()).toupper()
s.toupper();
s.tolower();
s.tolower().toupper()
fmt.Println(s)
}
Your return type is of String, for functions defined on pointers to String. It wouldn't make sense to be able to chain them.
tolower() and toupper() have pointer-to-String as the receivers, but they are returning String (not pointer-to-String).
You can fix this by changing one or the other.
e.g. change the signature of the function to either:
func (s *String) toupper() *String
or
func (s String) toupper() String
(see: http://play.golang.org/p/FaCD8AQtIX)
When you call a method with a pointer receiver on a variable (s in your example), then an address of that value will be taken automatically. So, you are basically calling (&s).toupper(). This mechanism works for all values that are addressable.
Return values of functions are not addressable unless you store them in a variable (so that they have a permanent place in the current stack frame or the heap).
I would recommend the following API, because it looks like the user of your string type is supposed to work with String and not *String. Therefore it makes sense to design a consistent API that also uses String to avoid confusion. Passing a string by value is extremely fast anyway, because they are implemented as pointers to immutable arrays internally:
func (s String) tolower() String {
return String(strings.ToLower(string(s)))
}
This method does not need a pointer receiver, because it doesn't modify the current string. It returns a new string instead. You can also easily chain those methods.
Alternatively, you can implement the methods this way:
func (s *String) tolower() *String {
*s = String(strings.ToLower(string(*s)))
return s
}
In this case, you keep returning the same pointer. So, in order to call (s.tolower()).toupper() you need to be able to take the address of s which is possible since you have assigned it to a variable. Then all further method calls in the chain are also possible, because you call them with a pointer to your initial variable. This differs from your attempt of chaining methods were each method call must have taken the address of a temporary variable in order to modify it (which isn't very useful).
maybe you can try this project: https://github.com/Laisky/go-chaining
import "github.com/Laisky/go-chaining"
func toLower(c *chaining.Chain) (interface{}, error) {
v := c.GetString()
return strings.ToLower(v), nil
}
func toUpper(c *chaining.Chain) (interface{}, error) {
v := c.GetString()
return strings.ToUpper(v), nil
}
func TestChainWithString(t *testing.T) {
f := func() (string, error) { return "aBcD", nil }
r := chaining.New(f()).
Next(toLower).
Next(toUpper)
expectVal := "ABCD"
if r.GetString() != expectVal {
t.Errorf("expect %v, got %v", expectVal, r.GetString())
}
}