Golang中的扩展方法是什么?

12

我是一个 .NET 开发人员。对 Go 语言非常新手。

在 .NET 中我们有扩展方法。Go 中有类似的东西吗?

在 .NET 中我会这样做 bsonTrans["trans.ticket"]

其中 bsonTrans => bson 文档

    "trans.ticket" => key in json

     trans is outer level and

     ticket is inner level

我正在使用本地的mongodb驱动程序。我添加了我的扩展函数来执行这些操作。

同样地,我在.NET上做到了第n个级别。

我想在Go中应用相同的逻辑。

示例

 b := []byte(trans)
var config map[string]interface{}
err := json.Unmarshal(b, &config)

fmt.Println(config["data"].(map[string] interface{})["issued"])
例如,在该示例中,我能像这样做吗:config["data.issued"],它应该返回相应的值吗?请帮助我弄清楚这个问题... 实际的JSON: (实际的JSON太大了,但是我提供了一个字段较少的示例。)
{
 "_id" : 2001,
    "address" : {
        "line1" : "",
        "line2" : "",
        "line3" : ""
       },
    "tickets" : [ 
        {
            "seq" : 2,
            "add" : [
              {
              "seq" : "",
              "amnt" : 50
              },

              {
              "seq" : "",
              "amnt" : 50
              {
              "seq" : "",
              "amnt" : 50
              }
              }

              }
             ]
}

不使用结构体的原因是我的JSON有太多嵌套结构,并且我有超过10个具有不同结构的模式。

所以我没有使用结构体。

我承认我不确定省略结构体是否是最好的方式。


2
你能否提供 JSON 的实际示例?这样我可以向你展示它是如何工作的。此外,您不希望使用正式的结构来编组数据吗,而要使用通用的 map[string]interface{} 吗?虽然后者也可以工作,但我更倾向于使用真正明确定义的结构进行编组。 - Cory LaNou
3个回答

33

扩展方法在.NET中的使用方式不被支持。

你可以尝试创建一个从字符串生成类型,并在该类型上创建一个方法作为最接近的替代方案:

type MyString string
func (m *MyString) Method() {
}

func main() {
    var s MyString = ""
    s.Method()
}

关于 "type MyString string" ... 是否有一种方法可以将字符串转换为MyString,而不需要任何附加的辅助函数或其他方式来实现MyString? Interface{} 能否做到这一点,或者在反射中是否会有运行时错误? - steviesama

5

更新2017:

Go语言支持为接收器类型添加扩展方法。

基于Go 1.9中的类型断言,您只需在类型定义处添加 = ,然后添加需要的方法即可。

type NewStruct = OldStrut
func (m *NewStruct) ExtensionMethod() {
}

调用它:

func main() {
    s := OldStruct{}
    s.ExtensionMethod()
}

1
当我尝试那样做时,我得到了这个编译错误:无法在非本地类型上定义新方法 - HairOfTheDog
修正方式是去掉等号,因此修正后的代码应为type NewStruct OldStrut - HairOfTheDog
@HairOfTheDog:正如我在答案中所写的,=仅适用于接收器类型。 - Mohsen
@HairOfTheDog:Mohsen的示例在Go 1.16中对我有效。如果我将其更改为type NewStruct OldStruct,那么我必须进行类型转换ns := NewStruct(s),这是OldStruct的副本而不是扩展方法。 - Hezi
我还没有学习过Go语言。"接收器类型"和"非接收器类型"之间有什么区别?(链接似乎没有回答这个问题) - Venryx
2
@Venryx:在Go语言中,接收器类型和值类型之间的区别有点像Dotnet中引用类型和值类型之间的区别。在这个具体的答案中,它意味着你不能做以下操作:struct MyCustomString = string - Mohsen

1
这是使用您的json的示例代码。 您的json样本不正确,因此我进行了更正以符合您的意图。
我认为使用带有深度嵌套结构的map[string]interface{}将无法有效工作,但我不知道您的用例,所以不能确定。
这是一个交互链接,也可以运行代码: http://play.golang.org/p/0gtYMfBMWX
package main

import "fmt"
import "encoding/json"

func main() {
  b := []byte(`{
  "tickets": [
    {
      "add": [
        {
          "amnt": 50,
          "seq": ""
        },
        {
          "amnt": 50,
          "seq": ""
        },
        {
          "amnt": 50,
          "seq": ""
        }
      ],
      "seq": 2
    }
  ],
  "address": {
    "line3": "",
    "line2": "",
    "line1": ""
  },
  "_id": 2001
}`)
  var config map[string]interface{}
  if err := json.Unmarshal(b, &config); err != nil {
    fmt.Printf("Error: %s", err)
    return
  }

  // I'm not sure what part of the data you are trying to get at here...
  //fmt.Println(config["data"].(map[string]interface{})["issued"])

  fmt.Printf("%v\n\n", config)

  tickets := config["tickets"]
  fmt.Printf("%v\n\n", tickets)

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接