英文:
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。
- 如何使用类型切换来处理任何(mgo)结构体?
- 在使用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.
- How can I use a type switch for any (mgo) struct?
- How do I cast this struct before I can use it with JSON.Marshall?
答案1
得分: 2
你真的应该了解你的类型,然而你有3个选项。
- 使用reflect。
示例:
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.
- Use reflect.
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
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论