45

I have the following struct which contains a net/http.Request:

type MyRequest struct {
    http.Request
    PathParams map[string]string
}

Now I want to initialize the anonymous inner struct http.Request in the following function:

func New(origRequest *http.Request, pathParams map[string]string) *MyRequest {
    req := new(MyRequest)
    req.PathParams = pathParams
    return req
}

How can I initialize the inner struct with the parameter origRequest?

deamon
  • 89,107
  • 111
  • 320
  • 448

4 Answers4

43
req := new(MyRequest)
req.PathParams = pathParams
req.Request = origRequest

or...

req := &MyRequest{
  PathParams: pathParams
  Request: origRequest
}

See: http://golang.org/ref/spec#Struct_types for more about embedding and how the fields get named.

Jeremy Wall
  • 23,907
  • 5
  • 55
  • 73
  • 1
    I get the compiler error `cannot use origRequest (type *http.Request) as type http.Request in assignment`. I guess this is because `Request` is not a named field. – deamon Sep 22 '12 at 20:15
  • 3
    nope it's because the type of the field is not the same as the type of origRequest. Use *origRequest instead and the problem goes away. – Jeremy Wall Sep 22 '12 at 20:22
  • You're right: derefencing with the asterisk or using a reference in the struct helps. Thanks. – deamon Sep 23 '12 at 11:08
  • As for how the fields get named: "The unqualified type name acts as the field name." So `http.Request` ends up being called just `Request`. – Jeffrey Martinez Aug 15 '15 at 00:44
21

What about:

func New(origRequest *http.Request, pathParams map[string]string) *MyRequest {
        return &MyRequest{*origRequest, pathParams}
}

It shows that instead of

New(foo, bar)

you might prefer just

&MyRequest{*foo, bar}

directly.

zzzz
  • 87,403
  • 16
  • 175
  • 139
  • 1
    How about when there is some field you don't want to initialize yourself, e.g., a file of type sync.Mutex? – Helin Wang Jul 16 '14 at 16:07
  • The zero value of a mutex should be a ready-to-use mutex, so you're good simply including it as an embedded value: `var hits struct { sync.Mutex n int } hits.Lock() hits.n++ hits.Unlock()` (from [10 things you probably didn't know about Go](https://talks.golang.org/2012/10things.slide#3)) – Flowchartsman Oct 16 '14 at 20:27
7

As Jeremy shows above, the "name" of an anonymous field is the same as the type of the field. So if the value of x were a struct containing an anonymous int, then x.int would refer to that field.

Matt
  • 1,424
  • 10
  • 15
1

Just for completeness sake, I'll add another example as well. Based on the comment from @Victor

This example shows another way recommended https://play.golang.org/p/Gbn8e6CTVi_c

type MyRequest struct {
    http.Request
    PathParams map[string]string
}

func New(origRequest *http.Request, pathParams map[string]string) *MyRequest {
    req := MyRequest{Request: origRequest, PathParams: pathParams}
    return req
}

Another comment from @Jeffery Martinez helped clarify it further:

As for how the fields get named: "The unqualified type name acts as the field name." So http.Request ends up being called just Request

i.e: The two following declarations are equivalent

// Version 1
type MyRequest struct {
    http.Request
    PathParams map[string]string
}

// Version 2
type MyRequest struct {
    Request http.Request
    PathParams map[string]string
}
Vance Palacio
  • 1,280
  • 12
  • 17