通过HTTP请求向现有列表追加数据

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

Appending to an existing list via http request

问题

我正在制作一个使用Echo创建简单REST API的过程中。我有一个变量,它是以下映射,基于我创建的结构体:

    type Checklist struct {
        ID         int      `json:"id"`
        Title      string   `json:"title"`
        Lines      []string `json:"lines"`
        AuthorName string   `json:"authorName"`
        AuthorID   int      `json:"authorID"`
        Tags       []Tag    `json:"tags"`
    }

    var (
        checklists    = map[int]*Checklist{}
        checklistSeq  = 1
        checklistLock = sync.Mutex{}
    )

在创建新的检查清单并将其附加到checklists变量之后,如何发送一个请求,将新的行添加到新的检查清单的Lines字段中?

我想到的解决方案是:

    func createChecklist(c echo.Context) error {
        checklistLock.Lock()
        defer checklistLock.Unlock()
        newChecklist := &Checklist{
            ID:    checklistSeq,
            Lines: make([]string, 0),
            Tags:  make([]Tag, 0),
        }
        if err := c.Bind(newChecklist); err != nil {
            return err
        }
        checklists[newChecklist.ID] = newChecklist
        checklistSeq++
        return c.JSON(http.StatusOK, newChecklist)
    }
    func addLine(c echo.Context) error {
        checklistLock.Lock()
        defer checklistLock.Unlock()
        id, _ := strconv.Atoi(c.Param("id"))
        checklist := *checklists[id]
        line := []string{""}
        if err := c.Bind(line); err != nil {
            return err
        }
        checklist.Lines = line
        return c.JSON(http.StatusCreated, checklists)
    }

然而,当我测试这个处理程序时,它给我返回以下结果:

    // 1: 创建一个新的检查清单

    $ curl -X POST -H 'Content-Type: application/json' -d '{"title": "test"}' localhost:1234/checklist

    >> {"id":1,"title":"test","lines":[],"authorName":"","authorID":0,"tags":[]}

    // 2: 检查是否已创建检查清单

    $ curl -X GET localhost:1234/checklist

    >> {"1":{"id":1,"title":"test","lines":[],"authorName":"","authorID":0,"tags":[]}}

    // 3: 尝试创建新行

    $ curl -X POST -H 'Content-Type: application/json' -d '{"lines": "test123"}' localhost:1234/checklist/1

    >> curl: (52) Empty reply from server

    // 4: 确认未创建新行

    $ curl -X GET localhost:1234/checklist

    >> {"1":{"id":1,"title":"test","lines":[],"authorName":"","authorID":0,"tags":[]}}

所以这个函数实际上不起作用,因为既没有从POST请求到适当的路由返回预期的响应,也没有将行添加到字段中。

英文:

I'm in the process of making a simple REST API using Echo. I have a variable which is the following map, based on this struct I've made:

    type Checklist struct {
	    ID         int      `json:"id"`
	    Title      string   `json:"title"`
	    Lines      []string `json:"lines"`
	    AuthorName string   `json:"authorName"`
	    AuthorID   int      `json:"authorID"`
	    Tags       []Tag    `json:"tags"`
    }

    var (
	    checklists    = map[int]*Checklist{}
	    checklistSeq  = 1
	    checklistLock = sync.Mutex{}
    )

After creating a new checklist and appending it to the checklists variable, how can I send a request which appends a new line in the Lines field of the new checklist?

The solution I thought up was this:

    func createChecklist(c echo.Context) error {
	    checklistLock.Lock()
	    defer checklistLock.Unlock()
	    newChecklist := &Checklist{
	  	    ID:    checklistSeq,
		    Lines: make([]string, 0),
		    Tags:  make([]Tag, 0),
	    }
	    if err := c.Bind(newChecklist); err != nil {
		    return err
	    }
	    checklists[newChecklist.ID] = newChecklist
	    checklistSeq++
	    return c.JSON(http.StatusOK, newChecklist)
    }
    func addLine(c echo.Context) error {
	    checklistLock.Lock()
	    defer checklistLock.Unlock()
	    id, _ := strconv.Atoi(c.Param("id"))
	    checklist := *checklists[id]
	    line := []string{""}
	    if err := c.Bind(line); err != nil {
		    return err
	    }
	    checklist.Lines = line
	    return c.JSON(http.StatusCreated, checklists)
    }

However, when I test this handler, it gives me the following results:

    // 1: Creating a new checklist

    $ curl -X POST -H 'Content-Type: application/json' -d '{"title": "test"}' localhost:1234/checklist

    >> {"id":1,"title":"test","lines":[],"authorName":"","authorID":0,"tags":[]}

    // 2: Check to see the checklist has been created.
 
    $ curl -X GET localhost:1234/checklist

    >> {"1":{"id":1,"title":"test","lines":[],"authorName":"","authorID":0,"tags":[]}}
    // 3: Attempting to create a new line
    $ curl -X POST -H 'Content-Type: application/json' -d '{"lines": "test123"}' localhost:1234/checklist/1

    >> curl: (52) Empty reply from server

    // 4: Confirming it hasn't been created.

    $ curl -X GET localhost:1234/checklist

    >> {"1":{"id":1,"title":"test","lines":[],"authorName":"","authorID":0,"tags":[]}}

So the function doesn't actually work, since neither the expected response comes back from pinging the POST to the appropriate route or the line is actually added to the field.

答案1

得分: 0

func addLine(c echo.Context) error {
    checklistLock.Lock()
    defer checklistLock.Unlock()

    id, err := strconv.Atoi(c.Param("id"))
    if err != nil {
        return err
    }

    // 不要解引用 *Checklist
    cl, ok := checklists[id]
    if !ok {
        return echo.ErrNotFound
    }

    // 使用与预期JSON相同的结构
    var input struct { Lines []string `json:"lines"` }

    // 始终传递 c.Bind 的指针
    if err := c.Bind(&input); err != nil {
        return err
    }

    // 不要覆盖先前写入的行,使用 append
    cl.Lines = append(cl.Lines, input.Lines...)

    return c.JSON(http.StatusOK, cl)
}

现在尝试:

$ curl -X POST -H 'Content-Type: application/json' -d '{"lines": ["test123"]}' localhost:1234/checklist/1
英文:
func addLine(c echo.Context) error {
    checklistLock.Lock()
    defer checklistLock.Unlock()

    id, err := strconv.Atoi(c.Param("id"))
    if err != nil {
        return err
    }

    // do not deref *Checklist
    cl, ok := checklists[id]
    if !ok {
        return echo.ErrNotFound
    }

    // use same structure as the expected JSON
    var input struct { Lines []string `json:"lines"` }

    // always pass a pointer to c.Bind
    if err := c.Bind(&input); err != nil {
        return err
    }

    // do not overwrite previously written lines, use append
    cl.Lines = append(cl.Lines, input.Lines...)

    return c.JSON(http.StatusOK, cl)
}

Now try:

$ curl -X POST -H 'Content-Type: application/json' -d '{"lines": ["test123"]}' localhost:1234/checklist/1

(notice that "test123" is enclosed in brackets)

huangapple
  • 本文由 发表于 2023年3月3日 16:04:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75624560.html
匿名

发表评论

匿名网友

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

确定