du4822 2018-02-23 00:34
浏览 27
已采纳

没有实例并将结果传递给func的Golang TypeOf

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?

  • 写回答

2条回答 默认 最新

  • duanguangsong2380 2018-02-23 09:06
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?