Golang TypeOf没有实例并将结果传递给func [英] Golang TypeOf without an instance and passing result to a func

查看:176
本文介绍了Golang TypeOf没有实例并将结果传递给func的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能在没有实例的情况下获取Type?我见过一些利用 reflect.TypeOf()的例子,但它们都处理一个实例。



以下是我尝试做的一个片段:

  import(
net / http


类型ParamReader struct {
//从中提取参数的请求
context * http。请求
}

//用特定的http请求初始化ParamReader。这用作
//作为我们param阅读器的上下文。所有后续调用将验证
//在此分配的http.Request
中存在的参数func(p * ParamReader)上下文(r * http.Request){
p.context = r
}

//验证给定参数's'是否存在以及类型为't'的有效
//值。如果从
//其字符串表示形式到't'的转换是可能的,则该值有效demaed
func(p * ParamReader)要求(s字符串,t类型){
// if上下文没有'
// addError('s'不存在)
//返回


if(t == typeof(uint64)) {
//如果不是s - > uint64
// addError('s'不是有效的uint64)
} else if(t == typeof(uint32)){
// ....
} / ....
}

我的例子是

  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)

如果h.ParamReader.HasErrors( ){
//迭代或者对错误做些什么
} else {
coolness:= h.ParamReader.ReadUint64(coolfactor)
email:= h.ParamReader。 ReadString(email)
money:= h.ParamReader.ReadUint64(0)
}
}

请注意,写完后我意识到我可以提供一个RequireUint64R equireUint32等等,也许这就是Go的方式吗?

解决方案

是的,这是可能的。诀窍是从一个指向类型的指针开始(它的值可以是一个类型 nil ,这非常好),然后使用 Type.Elem()来获取指向类型的 reflect.Type 描述符( base



$ t:=反映.TypeOf((* int)(nil)).elem()
fmt.Println(t)
$ b $ = reflect.TypeOf((* http.Request)(nil))。Elem ()
fmt.Println(t)
$ b $ = reflect.TypeOf((* os.File)(nil))。Elem()
fmt.Println(t)

输出(在 Go Playground ):

  int 
http .Request
os.File

请参阅相关问题:

Golang反映:获取类型表示名字?



如何获取类型的字符串表示形式?



如果要传递类型并在<$ c $中使用它们c> switch es,您可以像这样创建并将它们存储在全局变量中,并引用全局变量:

  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 (类型:int)
大小写httpRequestType:
fmt.Println(t reflect.Type){
switch t {
case intType:
fmt.Println类型:http.request)
case osFileType:
fmt.Println(Type:os.file)
case int64Type:
fmt.Println(Type:uint64 )
默认:
fmt.Println(Type:Other)
}
}

func main(){
printType(intType)
printType(httpRequestType)
printType(osFileType)
printType(int64Type)
}

上面的输出(在 Go Playground 上试用): p>

 类型:int 
类型:http.request
类型:o​​s.file
类型:uint64

但是说实话,如果你像这样使用它,而你没有使用 reflect.Type 的方法,然后创建常量要容易得多并且效率更高。它可能看起来像这样:

$ p $ type TypeDesc int
$ b $ 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)
案例类型OsFile:
fmt。 println(Type:os.file)
case typeInt64:
fmt.Println(Type:uint64)
default:
fmt.Println(Type:Other )


$ b $ func main(){
printType(typeInt)
printType(typeHttpRequest)
printType(typeOsFile)
printType(typeInt64)
}

输出是一样的。试试去游乐场


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?

解决方案

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.

这篇关于Golang TypeOf没有实例并将结果传递给func的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆