检查值的类型是否为结构体。

huangapple go评论84阅读模式
英文:

Check if value is typeof struct

问题

我想在Context上实现一个Send方法,该方法将给定的对象写入http.ResponseWriter

目前我有以下代码:

package context

import (
  "net/http"
)

type Context struct {
  Request           *http.Request
  ResponseWriter    http.ResponseWriter
}

type Handle func(*Context)

func New(w http.ResponseWriter, r *http.Request) *Context {
  return &Context{r, w}
}

func (c *Context) Send(value interface{}, code int) {
  c.WriteHeader(code)

  switch v := value.(type) {
    case string:
      c.Write([]byte(value))
    //default:
      //json, err := json.Marshal(value)

      //if err != nil {
      //  c.WriteHeader(http.StatusInternalServerError)
      //  c.Write([]byte(err.Error()))
      //}

      //c.Write([]byte(json))
  }
}

func (c *Context) WriteHeader(code int) {
  c.ResponseWriter.WriteHeader(code)
}

func (c *Context) Write(chunk []byte) {
  c.ResponseWriter.Write(chunk)
}

你可以看到,我将一些代码注释掉以便程序能够编译。我想在这部分实现支持自定义结构体,这些结构体应该被转换为JSON。

  1. 如何使用类型切换来处理任何(mgo)结构体?
  2. 在使用JSON.Marshal之前,如何对这个结构体进行类型转换?
英文:

I want to implement a Send method on Context which writes the given Object to the http.ResponseWriter.

At the moment I have:

package context

import (
  "net/http"
)

type Context struct {
  Request           *http.Request
  ResponseWriter    http.ResponseWriter
}

type Handle func(*Context)

func New(w http.ResponseWriter, r *http.Request) *Context {
  return &Context{r, w}
}

func (c *Context) Send(value interface{}, code int) {
  c.WriteHeader(code)

  switch v := value.(type) {
    case string:
      c.Write(byte(value))
    //default:
      //json, err := json.Marshal(value)

      //if err != nil {
      //  c.WriteHeader(http.StatusInternalServerError)
      //  c.Write([]byte(err.Error()))
      //}

      //c.Write([]byte(json))
  }
}

func (c *Context) WriteHeader(code int) {
  c.ResponseWriter.WriteHeader(code)
}

func (c *Context) Write(chunk []byte) {
  c.ResponseWriter.Write(chunk)
}

As you see I commented something out so the program compiles. What I want to do in that section is to support custom structs which should be transformed to JSON for me.

  1. How can I use a type switch for any (mgo) struct?
  2. How do I cast this struct before I can use it with JSON.Marshall?

答案1

得分: 2

你真的应该了解你的类型,然而你有3个选项。

示例:

func (c *Context) Send(value interface{}, code int) {
    c.WriteHeader(code)
    v := reflect.ValueOf(value)
    if v.Kind() == reflect.Struct || (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct) {
        json, err := json.Marshal(value)

        if err != nil {
            c.WriteHeader(http.StatusInternalServerError)
            c.Write([]byte(err.Error()))
            break
        }
        c.Write([]byte(json))
    } else {
        c.Write([]byte(fmt.Sprintf("%v", value)))
    }
}
  • 有两个不同的函数,一个用于结构体,一个用于原生类型,这是最清晰/最高效的方式。
  • select所有原生类型并处理它们,然后使用默认情况,就像你已经做的那样。

示例:

func (c *Context) Send(value interface{}, code int) {
    c.WriteHeader(code)

    switch v := value.(type) {
    case string:
        c.Write([]byte(v))
    case byte, rune, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
        float32, float64:
        c.Write([]byte(fmt.Sprintf("%v", v)))
    default: //everything else just encode as json
        json, err := json.Marshal(value)

        if err != nil {
            c.WriteHeader(http.StatusInternalServerError)
            c.Write([]byte(err.Error()))
            break
        }

        c.Write(json) //json is already []byte, check http://golang.org/pkg/encoding/json/#Marshal
    }
}
英文:

You really should know your types, however you have 3 options.

Example :

func (c *Context) Send(value interface{}, code int) {
	c.WriteHeader(code)
	v := reflect.ValueOf(value)
	if v.Kind() == reflect.Struct || v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct {
		json, err := json.Marshal(value)

		if err != nil {
			c.WriteHeader(http.StatusInternalServerError)
			c.Write([]byte(err.Error()))
			break
		}
		c.Write([]byte(json))
	} else {
		c.Write([]byte(fmt.Sprintf("%v", value)))
	}
}
  • Have 2 different functions, one for structs and one for native types, this is the cleanest / most efficient way.
  • select all native types and handle them then use default like you already.

Example:

func (c *Context) Send(value interface{}, code int) {
	c.WriteHeader(code)

	switch v := value.(type) {
	case string:
		c.Write([]byte(v))
	case byte, rune, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
		float32, float64:
		c.Write([]byte(fmt.Sprintf("%v", v)))
	default: //everything else just encode as json
		json, err := json.Marshal(value)

		if err != nil {
			c.WriteHeader(http.StatusInternalServerError)
			c.Write([]byte(err.Error()))
			break
		}

		c.Write(json) //json is already []byte, check http://golang.org/pkg/encoding/json/#Marshal
	}
}

huangapple
  • 本文由 发表于 2014年6月15日 02:04:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/24222761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定