I am learning Go and I am reading Go's official documentation about net/http, and I write following code from doc for test:
package main
import (
"net/http"
"fmt"
)
func main() {
client := &http.Client{}
resp, _ := client.Get("http://example.com")
fmt.Println(resp)
}
http.Client is a struct, but I do not know why there is a & pointer prefixed. I think creating a http.Client reference is not necessary. And why does the client variable have a Get method? I am reading the source code of net/http, it defines the Client struct below:
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
The Client struct does not have a Get method defined; why does the client variable have a Get method?
I would really take the Go Tour to get a feeling of the language and its basic syntax first.
The type declaration you quoted only contains the fields of the struct, but not its methods. Methods are defined elsewhere, like functions but with a receiver added which designates the type they belong to. For example the definition of Client.Get() method is this:
func (c *Client) Get(url string) (resp *Response, err error) {
req, err := NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
return c.Do(req)
}
The part before the method name is called the receiver, and that designates the type the method belogns to (*Client in this example). See Spec: Method declarations for more details.
The & is an address operator, it takes the address of its operand. In this case the local variable client will be of type *http.Client. http.Client{} is a composite literal which creates a value of the struct type http.Client, and & takes the address of the anonymous variable where this struct value is stored:
Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.
It is used so that the client variable will be a pointer to an http.Client value, one that is encouraged to be shared and reused:
The Client's Transport typically has internal state (cached TCP connections), so Clients should be reused instead of created as needed. Clients are safe for concurrent use by multiple goroutines.
And if client is a pointer, you are free to pass it around to other functions, only the pointer value will be copied, not the pointed http.Client struct, so the struct itself (the http.Client value) will be reused. Should you not use a pointer, if you would pass it to other functions, the struct itself would be copied and not reused.
Note that in this simple example it doesn't really matter, as even though all methods of http.Client are declared with pointer receiver, you can still call pointer methods on non-pointer variables, as client.Get() would be a shorthand for (&client).Get(). This is mentioned in Spec: Calls:
If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m().
So even though the & address operator is not needed in this simple example, it's good to keep the habit of using it, should the example grow or should you write code where this does matter (e.g. you pass around the created client).
Related
I want to create a net/url.URL and then use it in http.Client and http.Request constructs as follows
client := http.Client{
Timeout: 5 * time.Second,
}
req := http.Request{
URL: someKindOf_url.URL_type_I_have_already_initialised_elsewhere,
}
resp, err := client.Do(&req)
Upon req construction, I want to pass an (already existing) context.Context
The Request type does not seem to have such a field.
There is this NewRequestWithContext factory function, but uses a string for the URL and not a net/url.URL
Is there a way around this?
You should never create an http.Request object with a literal. Always use the constructor functions NewRequest or NewRequestWithContext. The constructor does a lot more than simply assigning simple values to a struct.
With this in mind, the correct way to achieve your goal would be, for example:
req := http.NewRequestWithContext(ctx, http.MethodGet, someKindOf_url.String(), nil)
That said, you can assign a context to an existing request:
req = req.WithContext(ctx)
http.Request doen't have a public context field, but have it private.
What you can do is use WithContext(ctx context.Context) method of http.Request
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 have defined two functions. When I pass a pointer to it, I can't get the defined method. Why is this?
type Visitor interface {
work()
}
func test(v *Visitor) {
v.work() // error
}
func test1(v Visitor) {
v.work() // ok
}
Error:
v.work undefined (type *Visitor is pointer to interface, not
interface)
anyone know why, ths
func test(v *Visitor) {
v.work() // error
}
v.work() ought to be a method call. But v is of type *Visitor, a pointer to interface. A pointer to interface has 0 methods, it does not implement anything (except the empty interface interface{}).
When using a non-pointer, the value v (or rather its type) has a method work(), so you can call that:
func test(v Visitor) {
v.work() // ok
}
Here v.work() works, because the v is of type Visitor which is an interface, and it contains the method work().
What may be confusing is that if you add method to a (non-pointer, non-interface) concrete type, the respective pointer type will also have that method, and you can call that. This is in Spec: Method sets:
A type may have a method set associated with it. The method set of an interface type is its interface. The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T). Further rules apply to structs containing embedded fields, as described in the section on struct types. Any other type has an empty method set. In a method set, each method must have a unique non-blank method name.
The difference is that you tried the same with interface type, which won't work. It works with concrete (non-interface) types. Lesson is to never use pointer to interface unless you can reason why it is needed (it is rarely needed).
As the error clearly states:
v.work undefined (type *Visitor is pointer to interface, not
interface)
This is because the work() function is called on pointer to the receiver but defined on value.
type Visitor interface {
work()
}
But you are passing pointer type receiver in second case in which you are getting an error.
In Golang spec Method sets are defined as:
A type may have a method set associated with it. The method set of an
interface type is its interface. The method set of any other type T
consists of all methods declared with receiver type T. The method set
of the corresponding pointer type *T is the set of all methods
declared with receiver *T or T (that is, it also contains the method
set of T). Further rules apply to structs containing embedded fields,
as described in the section on struct types. Any other type has an
empty method set. In a method set, each method must have a unique
non-blank method name.
One approach you can do is Implement the interface by using the struct on which you can call the method work().
package main
import "fmt"
type Visitor struct{}
type Visit interface {
work()
}
func test(v Visit) {
v.work() // error
fmt.Printf("%+v", v)
}
func (v *Visitor) work(){}
func main(){
v := Visitor{}
test(&v)
}
Working Code on Go playground
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.