Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么json包是';这里使用的解码和封送处理方法是什么?_Json_Go - Fatal编程技术网

为什么json包是';这里使用的解码和封送处理方法是什么?

为什么json包是';这里使用的解码和封送处理方法是什么?,json,go,Json,Go,在以下来自的示例中,用于为每个HTTP请求使用新的MongoDB会话实现HTTP服务器: 为什么在PostCategory函数中使用json包的Decode方法 为什么在GetCategories函数中使用json包的Marshal方法 起初我认为PostCategory中的Decode和GetCategories中的Marshal是相反的,但后来我发现在json包中有一个Unmarshal方法,可能还有一个Encode方法。所以我早些时候问过 这是节目单 package main impo

在以下来自的示例中,用于为每个HTTP请求使用新的MongoDB会话实现HTTP服务器:

  • 为什么在
    PostCategory
    函数中使用
    json
    包的
    Decode
    方法

  • 为什么在
    GetCategories
    函数中使用
    json
    包的
    Marshal
    方法

起初我认为
PostCategory
中的
Decode
GetCategories
中的
Marshal
是相反的,但后来我发现在
json
包中有一个
Unmarshal
方法,可能还有一个
Encode
方法。所以我早些时候问过

这是节目单

package main
import (
    "encoding/json"
    "log"
    "net/http"
    "github.com/gorilla/mux"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
)
var session *mgo.Session

type (
    Category struct {
Id bson.ObjectId `bson:"_id,omitempty"`
Name string
Description string
    }
    DataStore struct {
session *mgo.Session
    }
)
//Close mgo.Session
func (d *DataStore) Close() {
    d.session.Close()
}
//Returns a collection from the database.
func (d *DataStore) C(name string) *mgo.Collection {
    return d.session.DB("taskdb").C(name)
}
//Create a new DataStore object for each HTTP request
func NewDataStore() *DataStore {
    ds := &DataStore{
session: session.Copy(),
    }
    return ds
}

//Insert a record
func PostCategory(w http.ResponseWriter, r *http.Request) {
    var category Category
    // Decode the incoming Category json
    err := json.NewDecoder(r.Body).Decode(&category)
    if err != nil {
panic(err)
    }
    ds := NewDataStore()
    defer ds.Close()
    //Getting the mgo.Collection
    c := ds.C("categories")
    //Insert record
    err = c.Insert(&category)
    if err != nil {
panic(err)
    }
w.WriteHeader(http.StatusCreated)
}

//Read all records
func GetCategories(w http.ResponseWriter, r *http.Request) {
    var categories []Category
    ds := NewDataStore()
    defer ds.Close()
    //Getting the mgo.Collection
    c := ds.C("categories")
    iter := c.Find(nil).Iter()
    result := Category{}
    for iter.Next(&result) {
categories = append(categories, result)
    }
w.Header().Set("Content-Type", "application/json")
j, err := json.Marshal(categories)
if err != nil {
panic(err)
    }
w.WriteHeader(http.StatusOK)
w.Write(j)
}

func main() {
    var err error
    session, err = mgo.Dial("localhost")
    if err != nil {
panic(err)
    }
    r := mux.NewRouter()
r.HandleFunc("/api/categories", GetCategories).Methods("GET")
r.HandleFunc("/api/categories", PostCategory).Methods("POST")
    server := &http.Server{
Addr:    ":8080",
Handler: r,
    }
    log.Println("Listening...")
    server.ListenAndServe()
}

我认为这里使用
json.NewDecoder
的主要原因是直接从响应体(
r.body
)读取,因为
NewDecoder
io.Reader
作为输入


您可以使用
json.Unmarshal
,但随后必须首先将响应正文读入
[]字节
,并将该值传递给
json.Unmarshal
NewDecoder
在这里更方便。

我认为使用
json的主要原因。NewDecoder
在这里直接从响应体(
r.body
)读取,因为
NewDecoder
io.Reader
作为输入


您可以使用
json.Unmarshal
,但随后必须首先将响应正文读入
[]字节
,并将该值传递给
json.Unmarshal
NewDecoder
在这里更方便。

TL;DR-
封送
/
解组
获取并返回字节片,而
编码
/
解码
执行相同的操作,但从网络连接(读写器)等流中读取字节

包使用和类型对数据流进行操作,即“和”。这意味着您可以直接从网络套接字(或者在本例中是实现
io.Reader
)获取数据,并在字节进入时将其转换为JSON。通过这种方式,我们可以在任何数据可用但尚未收到整个文档之前立即开始处理JSON(在与大文档的慢速网络连接上,这可以节省我们很多时间,对于一些具有“无限大小”文档流的流协议,这是绝对必要的!)

Marshal
Unmarshal
不过是在字节片上操作的,这意味着您必须将整个JSON文档存储在内存中,然后才能使用它们。在您的示例中,作者使用Marshal是因为他们已经有了一个
[]字节
片,所以没有必要使用字节片构造一个缓冲区,然后制作一个使用该缓冲区的编码器,然后调用encode:相反,他们可以让Marshal为他们这样做

实际上,封送/解封只是编码器和解码器之上的方便方法。如果我们看一下,我们会发现它只是在构建一个编码器(或者编码器的内部表示,但是相信我,它们是一样的,如果你想证明的话,你可以看一下,它也在创建一个
编码状态
),然后返回输出字节:


TL;DR-
封送
/
解组
获取并返回字节片,而
编码
/
解码
执行相同的操作,但从网络连接(读写器)等流中读取字节

包使用和类型对数据流进行操作,即“和”。这意味着您可以直接从网络套接字(或者在本例中是实现
io.Reader
)获取数据,并在字节进入时将其转换为JSON。通过这种方式,我们可以在任何数据可用但尚未收到整个文档之前立即开始处理JSON(在与大文档的慢速网络连接上,这可以节省我们很多时间,对于一些具有“无限大小”文档流的流协议,这是绝对必要的!)

Marshal
Unmarshal
不过是在字节片上操作的,这意味着您必须将整个JSON文档存储在内存中,然后才能使用它们。在您的示例中,作者使用Marshal是因为他们已经有了一个
[]字节
片,所以没有必要使用字节片构造一个缓冲区,然后制作一个使用该缓冲区的编码器,然后调用encode:相反,他们可以让Marshal为他们这样做

实际上,封送/解封只是编码器和解码器之上的方便方法。如果我们看一下,我们会发现它只是在构建一个编码器(或者编码器的内部表示,但是相信我,它们是一样的,如果你想证明的话,你可以看一下,它也在创建一个
编码状态
),然后返回输出字节:


谢谢你是说
Unmarshal
Decode
可以应用于同一个对象,唯一的区别是该对象应该被视为
Unmarshal
的字节数组,而该对象应该被视为
io.Reader
对象?这基本上就是这个想法。事实上,如果您查看
解码
的源代码,您将看到它在内部也使用
解组
(尽管定义为私有包成员。()另外,
Decode
在您有一个实现
json.Unmarshaler
接口的类型时非常有用,因为它可以用于解码嵌套结构。例如,谢谢。您的意思是
Unmarshal
Decode
可以应用于同一个对象,唯一的区别是该对象应该被视为字节数组吗小于cod的y
func Marshal(v interface{}) ([]byte, error) {
    e := &encodeState{}
    err := e.marshal(v)
    if err != nil {
        return nil, err
    }
    return e.Bytes(), nil
}