My understanding of the uses of pointer receiver and value receiver is rather weak. Here's a scenario where I can't decide between the two:
I recently learned to re-use http.Client objects already created instead of creating a new http.Client each time, in order to benefit from connection pooling. So I did something like this:
type MailClient struct {
HTTPClient *http.Client
// ... bunch of other stuff
}
func newMailClient( // ... arguments for initializing stuff ) *MailClient {
return &MailClient{
HTTPClient: &http.Client{},
// ... init other stuff
}
}
func (c *MailClient) SendMail( // ... arguments that form a email request ) {
// ... prepare the email request
httpResp, err := c.HTTPClient.Do( // ... args for sending )
if err != nil {
// ... handle error
}
defer httpResp.Body.Close()
// ...
}
This way, as long as SendMail() is called on the same MailClient, I expect the connection pool to kick in (I understand the default MaxIdleConnsPerHost of the http.Transport is default to 2 without customization).
But notice I defined SendMail() to use a pointer receiver? Yup, I don't really know why I did it. I'm just hoping by using a pointer receiver, each time the method is called, it's the same instance of MailClient that's doing the work, and not a copy of it. I also thought the fact that value receiver prevents modifying the receiver is because it's a copy.
I also cautiously defined the HTTPClient field in the MailClient struct to be a pointer of http.Client, for the same reason - I don't know how value pointer works.
So here's to summarise my question:
Will value receivers result in a copy of the receiver being used in the method?
Will changing the receiver type to MailClient affect the connection pooling behavior?
Will changing the HTTPClient field to a http.Client affect the connection pooling behavior?
Connection pooling is implemented in http.Transport. Your application uses the default transport because the application does not set the client transport field.
No matter what the application does with pointer vs value receivers, there is no impact on connection pooling because the application uses the default transport.
The most important part to remember is that method calls translate to function calls with receivers. All rules that apply to function calls apply to method calls with the correspondent type of receiver (value or reference). A good way to see this is by using the following syntax
type XType struct {
A int
B *int
}
func (x XType) Mutate() {
x.A = 1
*x.B = 2
}
func (x *XType) MutateRef() {
x.A = 2
*x.B = 3
}
func main() {
i := 5
x1 := XType{
A: 9999,
B: &i,
}
//calling Mutate as a function passing the receiver by value
XType.Mutate(x1)
log.Printf("%#v", x1)
log.Printf("%#v", *x1.B)
//calling MutateRef as a function passing the receiver by reference
(*XType).MutateRef(&x1)
log.Printf("%#v", x1)
log.Printf("%#v", *x1.B)
}
Another thing to note is that when structs are passed by value, all fields are copied, imagine a pointer as an int, so a copy will still hold the same address value.
Now, it's easy to follow the answers for your questions:
Will value receivers result in a copy of the receiver being used in the method?
Yes, because is the same thing as calling a function passing a value, same rules apply
Will changing the receiver type to MailClient affect the connection pooling behavior
Not really, since the client is a pointer. Even if you call the method using a value receiver, you will still be using the client pointed by the value in your copy
Will changing the HTTPClient field to a http.Client affect the connection pooling behavior?
I don't think so, as the http.Transport is in charge of connection pooling and it is set by reference to the http.Client. Still, your best bet is to go with a pointer to a client
I want to make a copy of a context object - a request context to be exact, and make use of it later on in a separate go routine.
Problem is if I derive the request context using context.WithCancel(reqCtx) once the HTTP handler for this request is finished, not only will the original request context be cancelled, but also the copy of the request context will also be canceled.
I'd like to be able to copy the original request context and not have it canceled by the original context after the HTTP handler has finished executing.
Here's how to make a context that uses values from some other context, but not cancelation:
type valueOnlyContext struct{ context.Context }
func (valueOnlyContext) Deadline() (deadline time.Time, ok bool) { return }
func (valueOnlyContext) Done() <-chan struct{} { return nil }
func (valueOnlyContext) Err() error { return nil }
Use it like this:
ctx := valueOnlyContext{reqCtx}
Using the values without cancelation is probably outside the design intent of the context package. If the designers of the package thought this is a good thing, I would have expected them to bundle up the above in a context package function.
I've been using Gin's ShouldBind() method to bind form data to a struct:
type UpdateUserInfoContext struct {
Country string `json:"country"`
EmailAddr string `json:"emailAddr"`
LoginID string `json:"loginID"`
UserName string `json:"username"`
}
func (h *handler) updateUserInfo(ctx *gin.Context) {
var json UpdateUserInfoContext
if err := ctx.ShouldBind(&json); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
h.service.UpdateUserPassword(json)
ctx.JSON(http.StatusOK, "success")
}
But now I need to build a large, dynamic UPDATE SQL based on what is and isn't present in the body of a POST request. Since ShouldBind() binds to a struct I can't iterate over the values in the body without using reflection. I figured an easier way would be to see if there's a method to bind the requests to a map instead of a struct. There is the context method PostFormMap(key string), however as far as I can tell from the example given here (https://github.com/gin-gonic/gin#another-example-query--post-form), this method requires the values correspond to to the argument key in the request body. Does anyone have any experience doing this? Thank you!
package main
import (
"fmt"
"encoding/json"
)
func main() {
strbody:=[]byte("{\"mic\":\"check\"}")
mapbody:=make(map[string]string)
json.Unmarshal(strbody,&mapbody)
fmt.Println(fmt.Sprint("Is this thing on? ", mapbody["mic"]))
}
//returns Is this thing on? check
https://play.golang.org/p/ydLuLsY8qla
The situation I have now is the same as was asked about in this thread: Meaning of a struct with embedded anonymous interface?
type A interface {
Foo() string
}
type B struct {
A
bar string
}
Idiomatically, coming from a backround in OOP languages, what it looks like this pattern is "trying to say" to me is that B must implement interface A. But I get by now that "Go is different". So, rather than the compile-time check I expected at first, this is happy to compile with or without a
func (B) Foo() string { .... }
present. As the above question points out (paraphrased): "using embedded interfaces in structs is great for when you only want to implement /part/ of an interface".
Presumably, this is because what is happening with this embed is just like in every other case - a value of type B would have an anonymous interface value of type A, as a field. Personally while I find that orthogonality comforting, I also find it confusing that the reflection package would then let me get methods of A directly from B's type this way, and not error/nil if no method with receiver B is present. But - this question isn't about the thinking behind that - it is about how that interface value is initialized after b := B{}:
func main() {
bType := reflect.TypeOf(B{})
bMeth, has := bType.MethodByName("Foo")
if has {
fmt.Printf("HAS IT: %s\n",bMeth.Type.Kind())
res := bMeth.Func.Call([]reflect.Value{reflect.ValueOf(B{})})
val := res[0].Interface()
fmt.Println(val)
} else {
fmt.Println("DOESNT HAS IT")
}
}
When this is run, it causes a horrible panic
HAS IT: func
panic: runtime error: invalid memory address or nil pointer dereference
... or doesn't - depending on if the compiler/runtime was able to find the above method. So: How can I detect that situation before I trigger it?
That is - is there something about the bMeth value I can use to see that there is no "real" implementation present in the reflection-returned returned Method and func values? Is that more precisely something like "is the pointer to the function in the function table of the anonymous interface value in zero", or what exactly is going on with methods you pull from an interface with reflection where there is no implementation?
Wrapping the whole thing in a goroutine and attempting to run the function under defer/panic isn't the answer - not only because of the expense of the panic/defer but because the function in general might, if it does exist, have side effects I don't want right now...
Do I want something like a run-time implementation that mirrors the compiler's type check? Or is there an easier way? Am I thinking about this incorrectly?
Above example in a Go playground
You needn't reflection to my mind
method_in_table := B.Foo
fmt.Printf("%T \n", method_in_table)
will output you
func(main.B) string
Interface type A initialized at predeclared nil which has no dynamic type
var a A
if a==nil{
fmt.Printf("It's nil")
}
a.Foo()
will give you same error. So practical check can be just
if b.A != nil { b.Foo()}
This question is old with some good answers, but none presents the possibility that this can be done.
Before presenting the solution: I think it's not your job to make sure the implementation does not panic because it fails to set an embedded interface field. Someone could pass an implementation which explicitly defines the methods in which
panic() is called explicitly. You could not detect that case, yet, that implementation wouldn't be any better than a nil embedded interface field.
OK, so how to tell if a method cannot be called because it would panic due to the implementation not being available because the embedded interface field is nil?
You said you can't / don't want to call the method and recover from a panic because if the method is available, this would call it and have its side effect.
The fact is that we don't have to call it. We can just refer to the method via an instance (not type), and then the actual receiver has to be resolved. Of course if the receiver would be the dynamic value of an embedded interface, and if that interface is nil, the resolving will cause a runtime panic, but the method will not be called even if the embedded interface is not nil. Note that this is in fact a Method value, and obtaining a method value evaluates and saves the receiver. This receiver evaluation is what will fail.
Let's see an example:
type A interface {
Foo() string
}
type B struct {
A
}
func (b B) Int() int {
fmt.Println("B.Int() called")
return 0
}
func main() {
b := B{}
_ = b.Int
fmt.Println("We got this far, b.Int is realized")
}
What will this program output? Only "We got this far, b.Int is realized". Because the Int() method is explicitly defined for the B type, and so b.Int can be resolved. And since it's not called, "B.Int() called" will not be printed.
What if we do this:
_ = b.Foo
Since Foo is a promoted method from B.A embedded interface, and b.A is nil, resolving b.Foo will fail at runtime, and produce a runtime error, something like this:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x47d382]
goroutine 1 [running]:
main.main()
/tmp/sandbox877757882/prog.go:24 +0x2
But we can recover from this:
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
fmt.Println("This means b.Foo is not realized!")
}
}()
_ = b.Foo
This will output:
Recovered: runtime error: invalid memory address or nil pointer dereference
This means b.Foo is not realized!
Try the examples on the Go Playground.
Let me put my two cents in, after you've already received good answers for your question.
Presumably, this is because what is happening with this embed is just like in every other case - a value of type B would have an anonymous interface value of type A, as a field.
You've basically solved the problem here. This is just a field, but because it's anonymous all its methods are being promoted and you can use them directly on the struct. This is not only related to interfaces, but the problem you've pointed to exists within ordinary structures as well:
package main
type A struct {
}
func (a A) Foo() {
}
type B struct {
*A
}
func main() {
B{}.Foo()
}
This will cause panic. I believe this is expected: we're saying B embeds *A, but then leave it uninitialised, so what am I thinking? We could try to find an analogy here with, for example, C++ and find out it is similar to a null pointer in C++ – how do we deal with it there? We either expect it to be non-null (by a contract) or need to check before using. The latter it what Uvelichitel suggested in the accepted answer and it's by no means correct and there is no better solution I think. Although it's not very plausible. We do expect the caller to know the method they're calling is a promoted method of an anonymous field which is a pointer (or interface) type and as such can be nil. As an author of such code I would either need to make sure it's never nil (contract) or state it clearly in documentation that a caller needs to check it (but why would I embed this type then instead of having normal field, I'm not sure).
It bothers me with interfaces though, because looking back at your example and making A an interface, we have a following problem:
package main
import "fmt"
type A interface {
Foo()
}
type B struct {
A
}
func main() {
var b interface{}
b = &B{}
// Nicely check whether interface is implemented
if a, ok := b.(A); ok {
a.Foo()
}
}
Whoops, panic. I explicitly don't use reflect package here to indicate your problem exists within "normal" language usage. I have an interface object b and want to check whether it implements interface A. The answer is yes, but I'm getting panic. Who is to blame? I would feel much more comforting saying the creator of object behind the interface b who advertise some functionality, but don't care to provide the implementation. As such I would like it to call a bad practice or at least force it to be clearly stated in the documentation rather than assuming ok in the above type assertion means actually ok.
It's getting too long and off topic I think. My answer to your question is then a mixture of already given answers: directly check A is not null and if it's not possible (you don't know the exact field promoting the method), hope for the best and blame someone else.
I don't think this is possible. From what I can see in reflect's documentation and code, there is no way to know, whether a method is defined on the type or promoted. Seems like panic-recover is the best you can do here.
There are 3 questions here.
An embedded interface does not mean "implements A". It's exactly the same as embedding any other type of object. If you want to implement A, just make a method: func (b B) Foo() string.
When you say:
using embedded interfaces in structs is great for when you only want to
implement /part/ of an interface
That does work, but you have to make sure to create the object properly. Think of it like wrapping an existing object:
type MyReadCloser struct {
io.ReadCloser
}
func (mrc *MyReadCloser) Read(p []byte) (int64, error) {
// do your custom read logic here
}
// you get `Close` for free
func main() {
// assuming we have some reader
var rc io.ReadCloser
// you have to build the object like this:
myReader := MyReadCloser{rc}
}
I'm not sure how Go does it internally, but conceptually it's as if it creates a Close method for you:
func (mrc *MyReadCloser) Close() error {
return mrc.ReadCloser.Close()
}
The panic is because A is nil. If you had:
type concrete string
func (c concrete) Foo() string {
return string(c)
}
func main() {
b := B{A: c("test")}
// etc...
}
It would work. In other words when you call:
bMeth.Func.Call([]reflect.Value{reflect.ValueOf(B{})})
That's:
B{}.Foo()
Which is:
B{}.A.Foo()
And A is nil so you get a panic.
As to the question about how to get only the methods directly implemented by an object (not methods implemented by an embedded field), I wasn't able to see a way using the reflect library. MethodByName gives no indication:
<func(main.B) string Value>
Internally that's basically a function like this:
func(b B) string {
return b.A.Foo()
}
And I don't think there's anything in reflect that allows you to peer into the internals of a function. I tried looping over the fields, grabbing their methods and comparing the two, but that doesn't work either.
Given the following example, is it anyhow possible to create a function that can literally reproduce (not only get the reflect.Type) the actual type for further manipulation? I know go is statically typed and although it's very cool that I can pass any struct to a function that defines an interface parameter, is there any chance I can do more the other way around?
I already looked into the reflect package but only found stuff that returned a reflect.Type or reflect.Value. I used the New() method which returned a new reflect.Value - and there I couldn't set any fields. Maybe someone experienced with the reflect package can tell me if this is definitely possible or not - or if there's another way to do it.
package main
import "fmt"
type User struct {
Name string
}
func main() {
user := User{Name:"FooBar"}
DoSomethingGenericWithStruct(user)
}
func DoSomethingGenericWithStruct(i interface{}) {
// access fields of i ...
// or create slice of type of i ([]User) ...
// or instantiate new object of type of i (new User) ...
// ...
}
You would have to pass a pointer to your struct to be able to modify it.
Also keep in mind that using reflection has a high runtime performance cost.
func DoSomethingGenericWithStruct(i interface{}) {
val := reflect.ValueOf(i)
if val.Kind() != reflect.Ptr {
panic("need a pointer")
}
val = val.Elem() // now you can modify it
// add error checking and such, this will panic if it's not a struct or there's no "Name" field
val.FieldByName("Name").SetString("stuff")
}
playground
To create a new element and assign it:
val = val.Elem()
nval := reflect.New(val.Type()).Elem() // create a new struct of the same type
nval.FieldByName("Name").SetString("stuff")
val.Set(nval)
to modify the actual struct, not reflect.Value, you will have to get the interface{} to it then assert it to your type, for example:
nval := reflect.New(val.Type()).Elem() // create a new struct of the same type
user := nval.Interface().(User)
user.Name = "Stuff"
val.Set(reflect.ValueOf(user))