douzhi3105 2016-10-02 17:55
浏览 55

在go中使用空接口

I am trying to understand the code that is used at my company. I am new to go lang, and I have already gone through the tutorial on their official website. However, I am having a hard time wrapping my head around empty interfaces, i.e. interface{}. From various sources online, I figured out that the empty interface can hold any type. But, I am having a hard time figuring out the codebase, especially some of the functions. I will not be posting the entire thing here, but just the minimal functions in which it has been used. Please bear with me!

Function (I am trying to understand): 

func (this *RequestHandler) CreateAppHandler(rw http.ResponseWriter, r *http.Request) *foo.ResponseError {
    var data *views.Data = &views.Data{Attributes: &domain.Application{}}
    var request *views.Request = &views.Request{Data: data}


    if err := json.NewDecoder(r.Body).Decode(request); err != nil {
        logrus.Error(err)
        return foo.NewResponsePropogateError(foo.STATUS_400, err)
    }
    requestApp := request.Data.Attributes.(*domain.Application)
    requestApp.CreatedBy = user

Setting some context, RequestHandler is a struct defined in the same package as this code. domain and views are seperate packages. Application is a struct in the package domain. The following two structs are part of the package views:

type Data struct {
    Id         string      `json:"id"`
    Type       string      `json:"type"`
    Attributes interface{} `json:"attributes"`
}

type Request struct {
    Data *Data `json:"data"`
}

The following are part of the package json:

func NewDecoder(r io.Reader) *Decoder {
    return &Decoder{r: r}
}

func (dec *Decoder) Decode(v interface{}) error {
    if dec.err != nil {
        return dec.err
    }

    if err := dec.tokenPrepareForDecode(); err != nil {
        return err
    }

    if !dec.tokenValueAllowed() {
        return &SyntaxError{msg: "not at beginning of value"}
    }

    // Read whole value into buffer.
    n, err := dec.readValue()
    if err != nil {
        return err
    }
    dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
    dec.scanp += n

    // Don't save err from unmarshal into dec.err:
    // the connection is still usable since we read a complete JSON
    // object from it before the error happened.
    err = dec.d.unmarshal(v)

    // fixup token streaming state
    dec.tokenValueEnd()

    return err
}


type Decoder struct {
    r     io.Reader
    buf   []byte
    d     decodeState
    scanp int // start of unread data in buf
    scan  scanner
    err   error

    tokenState int
    tokenStack []int
}

Now, I understood that, in the struct Data in package views, Application is being set as a type for the empty interface. After that, a pointer to Request in the same package is created which points to the variable data.

I have the following doubts:

  1. What exactly does this keyword mean in Go? What is the purpose of writing this * RequestHandler?
  2. Initialization of a structure in Go can be done while assigning it to a variable by specifying the values of all it's members. However, here, for the struct Data, only the empty interface value is assigned and the values for the other two fields are not assigned?
  3. What is the advantage of assigning the Application struct to an empty interface? Does it mean I can use the struct members using the interface variable directly?
  4. Can someone help me figure out the meaning of this statement? json.NewDecoder(r.Body).Decode(request)?

While I know this is too much, but I am having a hard time figuring out the meaning of interfaces in Go. Please help!

  • 写回答

1条回答 默认 最新

  • dongpang1232 2016-10-02 19:41
    关注
    1. this is not a keyword in go; any variable name can be used there. That is called the receiver. A function declared in that way must be called like thing.func(params), where "thing" is an expression of the type of the receiver. Within the function, the receiver is set to the value of thing.

    2. A struct literal does not have to contain values for all the fields (or any of them). Any fields not explicitly set will have the zero value for their types.

    3. As you said, an empty interface can take on a value of any type. To use a value of type interface{}, you would use type assertion or a type switch to determine the type of the value, or you could use reflection to use the value without having to have code for the specific type.

    4. What specifically about that statement do you not understand? json is the name of a package in which the function NewDecoder is declared. That function is called, and then the Decode function (which is implemented by the type of the return value of NewDecoder) is called on that return value.

    You may want to take a look at Effective Go and/or The Go Programming Language Specification for more information.

    评论

报告相同问题?

悬赏问题

  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度