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

在golang中使用自己类型的最佳实践。阿利安人建造类型,go,types,Go,Types,我想知道什么时候或者是否应该在golang使用自己的类型。当这将更容易理解我的代码时,或者当我不应该使用自己的类型时 例如: 我想用MAC创建地图类型,并命名主机: 第一种方法是我能做到的最简单的方法 var machines map[string]string{ "11:22...": "myHost", "22:33..": "yourHost", } 第二条路 type MAC string type HOST string machines := map[MAC]H

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

例如: 我想用MAC创建地图类型,并命名主机:

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

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"),
    }
在上面的exmaple中,我可以在我的类型MAC上获得额外的控制,主机trought写入方法验证、比较等是否更好

第三条路

type MACHINES map[string]string

m := MACHINES{}
    m = map[string]string{
     "11:22.." : "myHost",
     "22:33" : "yourHost",
    }
对我来说,上述例子是最糟糕的,因为对其他人来说,理解不够直观。我认为上面的例子也应该是关于主机和MAC的,因为键入MACHINE并没有说明开发者应该如何实现它,所以我希望

  type MACHINES map[MAC]HOST

但是,请提供有关注释的信息,以便更好地了解在golang中使用自己的类型

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

在您的示例类型机器映射[string]string中,您将向您的类型添加一个名为string的方法

func (m MACHINES) String() string {
    s := "MACHINES\n"
    for k, v := range m {
        s += fmt.Sprintf("%v: %v\n", k, v)
    }
    return s
}
因为您实现了Stringer接口,所以接受Stringer接口的任何其他函数现在也可以接受您的机器类型

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

m := MACHINES{"foo":"bar", "baz": "bust"}
fmt.Printf("%s", m)
将调用字符串方法


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

在您的示例类型机器映射[string]string中,您将向您的类型添加一个名为string的方法

func (m MACHINES) String() string {
    s := "MACHINES\n"
    for k, v := range m {
        s += fmt.Sprintf("%v: %v\n", k, v)
    }
    return s
}
因为您实现了Stringer接口,所以接受Stringer接口的任何其他函数现在也可以接受您的机器类型

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

m := MACHINES{"foo":"bar", "baz": "bust"}
fmt.Printf("%s", m)
将调用字符串方法


在不评论具体示例的情况下,您通常希望使用新类型的原因如下:

您需要在类型上定义方法 您不希望该类型与派生类型的文本或变量具有可比性,例如,为了减少用户混淆,或确保他们不会执行无效操作,例如尝试将您的特殊字符串与其他随机字符串进行比较 您只需要一个地方来放置文档,或对返回特定类型的方法进行分组,例如,如果您有多个返回net.Conn的拨号方法,您可以创建一个Conn net.Conn类型并返回该类型,这只是为了在godoc中对Conn type头下的函数进行分组,或者为方法返回的net.Conn提供一般文档。 因为你希望人们能够检查某个泛型类型的东西是否来自你的包,例如,即使你的Conn只是一个普通的net.Conn,它也给你提供了类型切换和检查它是否是yourpackage.Conn的选项 您希望函数从预定义的事物列表中获取参数,而不希望用户能够生成可以传入的新值,例如未报告类型的导出常量列表
在不评论具体示例的情况下,您通常希望使用新类型的原因如下:

您需要在类型上定义方法 您不希望该类型与派生类型的文本或变量具有可比性,例如,为了减少用户混淆,或确保他们不会执行无效操作,例如尝试将您的特殊字符串与其他随机字符串进行比较 您只需要一个地方来放置文档,或对返回特定类型的方法进行分组,例如,如果您有多个返回net.Conn的拨号方法,您可以创建一个Conn net.Conn类型并返回该类型,这只是为了在godoc中对Conn type头下的函数进行分组,或者为方法返回的net.Conn提供一般文档。 因为你希望人们能够检查某个泛型类型的东西是否来自你的包,例如,即使你的Conn只是一个普通的net.Conn,它也给你提供了类型切换和检查它是否是yourpackage.Conn的选项 您希望函数从预定义的事物列表中获取参数,而不希望用户能够生成可以传入的新值,例如未报告类型的导出常量列表
只有当您需要添加额外的方法(如验证函数)或需要记录某些值(例如类型)的所需使用时,创建类型别名才有用

类型别名可以帮助您防止API误解,但如果您使用的是co,则不会 nstant值。例如,此代码是有效的:

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

有关常量在Go中如何工作的更多信息,请检查创建类型别名仅在需要添加额外方法(如验证函数)或需要记录某些值(例如类型)的所需使用时才有用

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

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

有关常量在Go中如何工作的更多信息,您可以查看我认为您确实希望使用自己的类型的

例如,所有字符串或整型的函数参数列表容易混淆,并且很容易出错


以及对类型名称的注释。MAC是媒体访问控制的首字母缩略词,所以它应该保持为所有CAP。但主人应该是主人,因为它只是一个词。我不记得确切的位置,但是有一个推荐的Go名称格式,它是所有大写缩写的CamelCase,比如GetIPv4AddressFromDNS,我认为您确实想使用自己的类型

例如,所有字符串或整型的函数参数列表容易混淆,并且很容易出错


以及对类型名称的注释。MAC是媒体访问控制的首字母缩略词,所以它应该保持为所有CAP。但主人应该是主人,因为它只是一个词。我不记得确切的位置,但是有一个推荐的Go名称形式,它是CamelCase,带有所有大写缩写,比如GetIPv4AddressFromDNS,我想这是使用您自己类型的另一个原因,这里没有提到,如果您不确定某事物的正确类型,例如uint8/uint16,并且您希望稍后在一个位置轻松更改它


但是,每当您想要使用内置类型的方法时,这就需要进行转换。或者您需要在自己的类型上定义它们。

我认为使用您自己的类型的另一个原因,这里没有提到,是如果您不确定某个对象的正确类型是什么,例如uint8/uint16,并且您希望稍后在一个位置轻松更改它


但是,每当您想要使用内置类型的方法时,这就需要进行转换。或者,您需要在自己的类型上定义它们。

定义map[MAC]主机时,您不需要键入字符串文本的类型名称。Package net的IP[]字节类型是一种具有基本地址类型的先例,但它正在进行一些实际的二进制字符串转换,并将4字节和16字节IP视为IPv4和IPv6。我看到的主机类型用处不大,在正常的Go大写规则下也会被命名为host。我倾向于不添加类型,除非你最终得到了很多你想在它们中做的事情。命名类型的原因几乎总是定义方法。只有当你想扩展字符串或整数的行为时才使用新类型。例如,在你的情况下,我不明白为什么要使用新类型。此外,Go有一个定义良好的封装系统,私有字段使用小写,公共字段使用大写,因此创建变量和类型时都使用大写,就像MAC在Go中看起来不太好一样,在其他语言中可能是这样,但在Go中不是惯用的。在定义map[MAC]主机时,不需要键入字符串的类型名。Package net的IP[]字节类型是一种具有基本地址类型的先例,但它正在进行一些实际的二进制字符串转换,并将4字节和16字节IP视为IPv4和IPv6。我看到的主机类型用处不大,在正常的Go大写规则下也会被命名为host。我倾向于不添加类型,除非你最终得到了很多你想在它们中做的事情。命名类型的原因几乎总是定义方法。只有当你想扩展字符串或整数的行为时才使用新类型。例如,在你的情况下,我不明白为什么要使用新类型。此外,Go有一个定义良好的封装系统,私有字段使用小写,公共字段使用大写,所以创建变量和类型都使用大写,就像MAC在Go中看起来不好一样,在其他语言中可能是这样,但在Go中不是惯用的。是的,是的。这是唯一的例子。对我来说,重要的是使用自己的类型何时、为何以及何时不使用。铜版纸。这是唯一的例子。对我来说,重要的是使用自己的类型何时、为何以及何时不使用。谢谢