在golang中使用自己的类型的最佳实践.阿利亚人建造类型



我想知道什么时候或者是否应该在golang中使用自己的类型。当这将更友好地理解我的代码,或者当我不应该使用自己的类型。

的例子:我想用MAC创建map类型,并且名称host:

第一种方法是我能做到的最简单的方法

var machines map[string]string{
   "11:22...": "myHost",
   "22:33..":  "yourHost",
}

type MAC string
type HOST string
  machines := map[MAC]HOST{
       MAC("11:22..") : HOST("myHost"),
       MAC("22:33..") : HOST("yourHost"),
    }

在上面的例子中,我可以获得额外的控制我的类型MAC, HOST通过写入方法来验证,比较等,它更好吗?

第三条道路

type MACHINES map[string]string
m := MACHINES{}
    m = map[string]string{
     "11:22.." : "myHost",
     "22:33" : "yourHost",
    }
上面的例子对我来说是最难理解的,对其他人来说不是很直观。我认为上面的例子也应该填充HOST和MAC,因为类型MACHINE没有说明开发人员应该如何实现所以我想要

  type MACHINES map[MAC]HOST

但是,为了更好地理解在golang中使用自己的类型,请给出注释。

在不注释具体示例的情况下,通常有几个原因会让您想要使用新类型:

  • 需要在
  • 类型上定义方法
  • 您不希望该类型与字面量或与其派生类型的变量(例如;以减少用户混淆或确保他们不会做一些无效的事情,如试图将您的特殊字符串与其他随机字符串进行比较)
  • 你只需要一个地方来放置文档,或者对返回特定类型的方法进行分组(例如:如果您有几个返回net.Conn的Dial方法,那么您可以创建一个type Conn net.Conn并返回它,而不是仅仅为了将godoc中的Conn类型头下的函数分组,或者为网络提供通用文档。
  • 因为您希望人们能够检查泛型类型的东西是否来自您的包(例如。即使你的Conn只是一个普通的网。Conn,它提供了类型切换的选项,并检查它是否是一个yourpackage。Conn也)
  • 你想要一个函数从预定义的列表中获取参数,你不希望用户能够创建可以传递的新值(例如:未导出类型的导出常量列表)

创建类型别名仅在需要添加额外的方法(例如验证函数)或想要记录某些值的期望使用时才有用(例如,net。IP类型)。

类型别名可以帮助您防止API误解,但如果您使用常量值则不起作用。例如,以下代码是有效的:

type Host string
type Mac string
hosts := map[Mac]Host{"ad:cb..": "localhost"}

有关常量如何在Go中工作的更多信息,您可以查看Rob Pike的博客文章

Go最重要的特性之一是接口。在Go中,通过定义接口的方法来实现接口,实现接口的唯一方法是将方法添加到类型中。例如,假设您想从fmt包实现Stringer接口。

在您的示例type MACHINES map[string]string中,您将添加一个名为String的方法到您的类型。

func (m MACHINES) String() string {
    s := "MACHINESn"
    for k, v := range m {
        s += fmt.Sprintf("%v: %vn", k, v)
    }
    return s
}

任何其他接受Stringer接口的函数现在也可以接受你的MACHINES类型,因为你实现了Stringer接口。

例如,fmt.Printf检查传入类型是否实现了Stringer接口

m := MACHINES{"foo":"bar", "baz": "bust"}
fmt.Printf("%s", m)

将调用MACHINES字符串方法

操场上的例子

在我看来,你应该使用你自己的类型。

作为一个例子,函数参数列表如果全是"string"或全是"int",就很容易混淆,很容易出错。

和类型名称注释。"MAC"是媒体访问控制(Media Access Control)的首字母缩写,所以应该保持全大写。但是"HOST"应该是"HOST",因为它只是一个单词。具体在哪我不记得了,但有一种推荐的Go名称格式是CamelCase全大写缩写,比如GetIPv4AddressFromDNS

我认为使用自己的类型的另一个原因,这里没有提到,如果你不确定正确的类型是什么,例如uint8/uint16,你想在一个地方轻松地改变它。

然而,当你想使用内置类型的方法时,这将使转换成为必要。或者您需要在自己的类型中定义它们。

最新更新