Go接口(interface)方法使用

标签 go

我使用 Martini 库编写了一个非常简单的 Go 应用程序。在整理一个简单的 REST API 示例时,我想在发生错误时将 JSON 数据渲染回用户,如下所示:

{
    error: "Document Not Found",
    code: 404
}

我使用以下代码返回 Martini 可以呈现为 JSON 的 map 。 包错误响应

import "net/http"

type ErrJson interface {

    RenderErr(v int)

}

func RenderErr(v int) map [string]interface{} {

    var returnMap = map[string]interface{} {
        "error": http.StatusText(v),
        "code": v,
    }

    return returnMap

}

稍后在我的 Controller 代码中,我尝试使用测试此方法

fmt.Println(ErrJson.RenderErr(400))

但是我收到以下错误:

controllers\FoodController.go:25: cannot use 400 (type int) as type ErrorResponces.ErrJson in function argument: int does not implement ErrorResponces.ErrJson (missing RenderErr method)

controllers\FoodController.go:25: not enough arguments in call to ErrorResponces.ErrJson.RenderErr controllers\FoodController.go:25: ErrorResponces.ErrJson.RenderErr(400) used as value

我很难弄清楚这个错误到底在说什么。

最佳答案

您似乎正在尝试直接在接口(interface)类型上调用函数,而不是在实现该接口(interface)的对象上调用函数。

这是一个返回 JSON 数据的简单示例:

package main

import (
  "encoding/json"
  "github.com/codegangsta/martini"
  "net/http"
)

func Encode(v ...interface{}) (string, error) {
  var data interface{} = v
  if v == nil {
    // So that empty results produces `[]` and not `null`
    data = []interface{}{}
  } else if len(v) == 1 {
    data = v[0]
  }
  b, err := json.Marshal(data)
  return string(b), err
}

func RenderErr(v int) map[string]interface{} {
  var returnMap = map[string]interface{}{
    "error": http.StatusText(v),
    "code":  v,
  }

  return returnMap
}

func main() {
  m := martini.Classic()
  m.Get("/", func(c martini.Context, w http.ResponseWriter, r *http.Request) string {
    w.Header().Set("Content-Type", "application/json")

    str, err := Encode(RenderErr(400))
    if err != nil {
      panic(err)
    }

    return str
  })
  m.Run()
}

如果你想使用你的界面创意,你可以做这样的事情(我试图复制你基本上在做的事情):

package main

import (
  "encoding/json"
  "github.com/codegangsta/martini"
  "net/http"
)

func Encode(v ...interface{}) (string, error) {
  var data interface{} = v
  if v == nil {
    // So that empty results produces `[]` and not `null`
    data = []interface{}{}
  } else if len(v) == 1 {
    data = v[0]
  }
  b, err := json.Marshal(data)
  return string(b), err
}

type ErrJson interface {
  RenderErr() string
}

type ErrJsonCode int

func (e ErrJsonCode) RenderErr() string {
  var returnMap = map[string]interface{}{
    "error": http.StatusText(int(e)),
    "code":  int(e),
  }

  str, err := Encode(returnMap)
  if err != nil {
    panic(err)
  }

  return str
}

func main() {
  m := martini.Classic()
  m.Get("/", func(c martini.Context, w http.ResponseWriter, r *http.Request) string {
    w.Header().Set("Content-Type", "application/json")
    return ErrJsonCode(400).RenderErr()
  })
  m.Run()
}

我不确定我会这样设计它。我可能会使其更加通用并支持多种内容类型,并且不会出现与其内容类型相关的错误。这是一篇关于使用 Martini 构建 Restful API 的不错的文章:http://0value.com/build-a-restful-API-with-Martini (它使用了一些先进的概念)。

关于Go接口(interface)方法使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20715905/

相关文章:

go - 将 []*io.PipeWriter 传递给 io.MultiWriter

arrays - 我可以在 Go 中使用 "displaced"数组基数吗?

struct - 如何动态清除类型结构实例的值

go - 无法在 Fedora 31 中安装 gopls

macos - 安全 : SecKeychainSearchCopyNext Error - Unable to Install Delve on MacOS

android - 如何使用gomobile build sdk-arr-libs访问web?

go - 将界面转换为另一个界面并复制内容

go - 如何使用 Go 获取客户端 DNS IP

go - 如何漂亮地打印一个 Golang 结构?

go - 如何在 cgo 导出函数中获取正确的参数名称?