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())
}
}
Related
Suppose I have a lot of different structs, but they all share a common field, such as "name". For example:
type foo struct {
name string
someOtherString string
// Other fields
}
type bar struct {
name string
someNumber int
// Other fields
}
Further on in the program, I repeatedly encounter the situation where I get pointers to these structs (so *foo, *bar, etc.) and need to perform operations depending on whether the pointer is nil or not, basically like so:
func workOnName(f *foo) interface{} {
if (f == nil) {
// Do lots of stuff
} else {
// Do lots of other stuff
}
// Do even more stuff
return something
}
This function, which only uses name, is the same across all structs. If these were not pointers, I know I could write a common interface for each struct that returns the name and use that as the type. But with pointers, none of this has worked. Go either complains while compiling, or the nil check doesn't work and Go panics. I haven't found anything smarter than to copy/paste the exact same code for every struct that I have, so basically to implement all the functions:
func (f *foo) workOnName() interface{}
func (b *bar) workOnName() interface{}
func (h *ham) workOnName() interface{}
// And so on...
Is there a way to do this better, i.e. to only implement a simple function (or even better, no function at all) for all my structs and simply write the complicated stuff once, for all the structs?
Edit: Thank you to the answers so far, but simply using an interface of the type:
func (f foo) Name() string {
return f.name
}
for some interface that provides Name() does not work, because the pointer is not recognized as nil. See this playground: https://play.golang.org/p/_d1qiZwnMe_f
You can declare an interface which declares a function returning a name:
type WithName interface {
Name() string
}
In order to implement that interface, you types (foo, bar, etc) need to have that method - not just the field, the method.
func (f foo) Name() string {
return f.name
}
Then, workOnName needs to receive a reference of that interface:
func workOnName(n WithName) interface{} {
if (n == nil || reflect.ValueOf(n).isNil()) {
// Do lots of stuff
} else {
// Do lots of other stuff
}
// Do even more stuff
return something
}
Keep in mind that the parameter n WithName is always treated as a pointer, not an object value.
I think that's the case for reflect.
Something like:
package main
import (
"fmt"
"reflect"
)
func SetFieldX(obj, value interface{}) {
v := reflect.ValueOf(obj).Elem()
if !v.IsValid() {
fmt.Println("obj is nil")
return
}
f := v.FieldByName("X")
if f.IsValid() && f.CanSet() {
f.Set(reflect.ValueOf(value))
}
}
func main() {
st1 := &struct{ X int }{10}
var stNil *struct{}
SetFieldX(st1, 555)
SetFieldX(stNil, "SSS")
fmt.Printf("%v\n%v\n", st1, stNil)
}
https://play.golang.org/p/OddSWT4JkSG
Note that IsValid checks more than just obj==nil but if you really want to distinguish cases of nil pointers and non-struct objects - you are free to implement it.
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.
Is it possible in go to get a "Type" without an instance? I've seen some examples that utilize reflect.TypeOf() but they all deal with an instance.
Below is a snippet of what I am attempting to do:
import (
"net/http"
)
type ParamReader struct {
// The request from which to extract parameters
context *http.Request
}
// Initialize the ParamReader with a specific http request. This serves
// as the 'context' of our param reader. All subsequent calls will validate
// the params that are present on this assigned http.Request
func (p *ParamReader) Context(r *http.Request) {
p.context = r
}
// Validate that a given param 's' is both present and a valid
// value of type 't'. A value is demeed valid if a conversion from
// its string representation to 't' is possible
func(p *ParamReader) Require(s string, t Type) {
// if context not have 's'
// addError('s' is not present)
// return
if( t == typeof(uint64)) {
// If not s -> uint64
// addError('s' is not a valid uint64)
} else if (t == typeof(uint32)) {
// ....
} / ....
}
An example of my usage would be
func (h *Handler) OnRequest(r *http.Request) {
h.ParamReader.Context(r)
h.ParamReader.Require("age", uint16)
h.ParamReader.Require("name", string)
h.ParamReader.Require("coolfactor", uint64)
h.ParamReader.Optional("email", string, "unspecified")
h.ParamReader.Optional("money", uint64, "0")
if h.ParamReader.HasErrors() {
// Iterate or do something about the errors
} else {
coolness := h.ParamReader.ReadUint64("coolfactor")
email := h.ParamReader.ReadString("email")
money := h.ParamReader.ReadUint64(0)
}
}
Note, after writing this out, I realize I could provide a "RequireUint64", "RequireUint32", etc.. perhaps that would be the Go way?
Yes, it's possible. The trick is to start from a pointer to the type (whose value can be a typed nil, that's perfectly OK), and then use Type.Elem() to get the reflect.Type descriptor of the pointed type (the base type).
See some examples:
t := reflect.TypeOf((*int)(nil)).Elem()
fmt.Println(t)
t = reflect.TypeOf((*http.Request)(nil)).Elem()
fmt.Println(t)
t = reflect.TypeOf((*os.File)(nil)).Elem()
fmt.Println(t)
Output (try it on the Go Playground):
int
http.Request
os.File
See related questions:
Golang reflect: Get Type representation from name?
How to get the string representation of a type?
If you want to pass around the types and use them in switches, you can create and store them in global variables once like this, and refer to the global vars:
var (
intType = reflect.TypeOf((*int)(nil))
httpRequestType = reflect.TypeOf((*http.Request)(nil))
osFileType = reflect.TypeOf((*os.File)(nil))
int64Type = reflect.TypeOf((*uint64)(nil))
)
func printType(t reflect.Type) {
switch t {
case intType:
fmt.Println("Type: int")
case httpRequestType:
fmt.Println("Type: http.request")
case osFileType:
fmt.Println("Type: os.file")
case int64Type:
fmt.Println("Type: uint64")
default:
fmt.Println("Type: Other")
}
}
func main() {
printType(intType)
printType(httpRequestType)
printType(osFileType)
printType(int64Type)
}
Output of the above (try it on the Go Playground):
Type: int
Type: http.request
Type: os.file
Type: uint64
But honestly, if you're using it like this way and you're not using reflect.Type's methods, then creating constants is much easier and more efficient. It could look like this:
type TypeDesc int
const (
typeInt TypeDesc = iota
typeHttpRequest
typeOsFile
typeInt64
)
func printType(t TypeDesc) {
switch t {
case typeInt:
fmt.Println("Type: int")
case typeHttpRequest:
fmt.Println("Type: http.request")
case typeOsFile:
fmt.Println("Type: os.file")
case typeInt64:
fmt.Println("Type: uint64")
default:
fmt.Println("Type: Other")
}
}
func main() {
printType(typeInt)
printType(typeHttpRequest)
printType(typeOsFile)
printType(typeInt64)
}
Output is the same. Try it on the Go Playground.
I'm fairly certain this isn't possible in Go. While it's far from ideal you can use Type.Name() and a string as the functions arg to do whatever comparisons are necessary.
package main
import (
"fmt"
"reflect"
)
func main() {
printIt("int")
}
func printIt(x string) {
i := 10
if (reflect.TypeOf(i).Name() == x) {
fmt.Println(x)
}
}
When I define function
func test(a int, b int) int {
//bla
}
I must set arguments and return value types. How I can return value based on argument type, ex
func test(argument type) type {
//if argument type == string, must return string
//or else if argument int, must return integer
}
Can I do this and how?
Go lacks generics, (not going to argue this point one way or the other), you can achieve this by passing interface{} to functions and then doing a type assertion on the other side.
package main
import "fmt"
func test(t interface{}) interface{} {
switch t.(type) {
case string:
return "test"
case int:
return 54
}
return ""
}
func main() {
fmt.Printf("%#v\n", test(55))
fmt.Printf("%#v", test("test"))
}
You will have to type assert the value you get out
v := test(55).(int)
Go does not yet have generics like C# or Java.
It does have an empty interface (interface{})
Here is code that I believe answers your question, if I understood it correctly:
package main
import (
"fmt"
"reflect"
)
type generic interface{} // you don't have to call the type generic, you can call it X
func main() {
n := test(10) // I happen to pass an int
fmt.Println(n)
}
func test(arg generic) generic {
// do something with arg
result := arg.(int) * 2
// check that the result is the same data type as arg
if reflect.TypeOf(arg) != reflect.TypeOf(result) {
panic("type mismatch")
}
return result;
}
If I have a struct like this
type myStruct struct {
mystring string
myint int
}
and if I have a function that returns a new myStruct like this
func New() myStruct {
s := myStruct{}
s.mystring = "string"
s.myint = 1
return s
}
Because I first store it in the "s" variable before returning it, is my function actually making 2 myStruct values instead of one?
And if so, is it then a better practice to make sure I don't first store it in the variable?
The return statement will return a copy of the myStruct object value. If it is a small object then this is fine.
If you intend for the caller to be able to modify this object, and the struct will have methods that use a pointer as the receiver, then it makes more sense to return a pointer to your struct instead:
func New() *myStruct {
s := myStruct{}
s.mystring = "string"
s.myint = 1
return &s
}
You can see the copy happening when you compare the memory address of value vs pointer return types: http://play.golang.org/p/sj6mivYSHg
package main
import (
"fmt"
)
type myStruct struct {
mystring string
myint int
}
func NewObj() myStruct {
s := myStruct{}
fmt.Printf("%p\n", &s)
return s
}
func NewPtr() *myStruct {
s := &myStruct{}
fmt.Printf("%p\n",s)
return s
}
func main() {
o := NewObj()
fmt.Printf("%p\n",&o)
p := NewPtr()
fmt.Printf("%p\n",p)
}
0xf8400235a0 // obj inside NewObj()
0xf840023580 // obj returned to caller
0xf840023640 // ptr inside of NewPtr()
0xf840023640 // ptr returned to caller
I'm definitely not a Go expert (or even novice :) ), but as #max.haredoom mentioned, you can allocate variables in the function signature itself. In that way, you can also omit the s in the return:
package main
import "fmt"
type myStruct struct {
mystring string
myint int
}
func New() (s myStruct) {
s.mystring = "string"
s.myint = 1
return
}
func main() {
r := New()
fmt.Println(r)
}
// Outputs {string 1}
In the examples that I have come across in Effective Go, it does seem to be the most common way of doing things of this nature, but again, I am definitely not an authority on the subject (and will look for additional info on the actual performance).
I think I found the answer by using defer.
I updated the function so that there's a deferred modification to the myStruct value. This means it will happen after the return, but before it is received on the other end.
When I do this, the struct that is received by the caller does not show the updated value, so it appears as though I am indeed returning a copy.
func New() myStruct {
s := myStruct{}
defer func() {
s.mystring = "new value" // defer an update to the value
}()
s.mystring = "string"
s.myint = 1
return s
}
func main() {
b := New()
fmt.Println(b) // still shows the original value
}
http://play.golang.org/p/WWQi8HpDny