英文:
Why create go types based on other?
问题
定义新类型的目的是什么:
type NewType OldType
由于NewType只有方法声明,所以:
var x NewType
也可以存储OldType的“对象”。这样做有什么优势吗?
英文:
what is the purpose of defining new types in go:
type NewType OldType
since NewType have only methods declarations, so:
var x NewType
can store also OldType 'objects'. Are there any advantages?
答案1
得分: 5
一般来说,给类型命名的原因非常简单,大多数语言都是一样的 - 可以给复杂的类型命名,比如:
<!-- language: golang -->
type Person struct{
name String
age uint8
}
然而,像你描述的这样命名类型,我称之为“类型别名”(不确定其他人是否使用这个术语,但这是我常用的术语),并没有给你上述提到的优势。然而,它确实给你提供了一种在现有类型上添加方法的能力。Go不允许你在你没有自己定义的现有类型上添加方法(即内置类型或在其他包中定义的类型),所以类型别名允许你假装你自己定义了它们,并且因此可以在它们上添加方法。另一种很好的思考方式是,它类似于在面向对象的语言(比如Java)中创建包装类型的更简洁版本。
所以,假设我想将整数用作错误。在Go中,error
接口只需要一个名为“Error”的方法,该方法返回一个字符串。使用类型别名,我可以这样做:
<!-- language: golang -->
type errorCode int
func (e errorCode) Error() string {
return fmt.Sprintf("%d", e)
}
...然后我可以使用整数错误码。相比之下,如果我尝试以下操作,将会出错:
<!-- language: golang -->
func (e int) Error() string {
return fmt.Sprintf("%d", e)
}
为了演示,请查看这个实现:
http://play.golang.org/p/9NO6Lcdsbq
只是为了澄清(因为我使用“别名”这个词可能会误导),在其他方面等效的两种类型(例如上面示例中的int
和errorCode
)是不能互换的。Go类型系统将它们视为根本不同的类型,尽管你可能能够在它们之间进行类型转换。
英文:
The reason behind naming types in general is fairly straightforward, and is much the same in most languages - being able to name complex types, like:
<!-- language: golang -->
type Person struct{
name String
age uint8
}
However, naming a type like you described, which I'll call "type aliasing" (not sure if this is used by anyone else, but it's the term I tend to use), doesn't give you the above-mentioned advantage. What it <i>does</i> give you, however, is the ability to add methods to existing types. Go disallows you from adding methods to existing types that you did not define yourself (ie, built-in types or types defined in other packages), so aliasing allows you to pretend that you <i>did</i> define them yourself, and thus add methods to them. Another good way to think about it is like a much more concise version of creating a wrapper type (as you would in an OO language like Java, for example).
So, let's say that I wanted to be able use integers as errors. In Go, the error
interface simply requires a method called "Error" which returns a string. Using type aliasing, I could do:
<!-- language: golang -->
type errorCode int
func (e errorCode) Error() string {
return fmt.Sprintf("%d", e)
}
...and I could use integer error codes. By contrast, if I tried the following, I would get an error:
<!-- language: golang -->
func (e int) Error() string {
return fmt.Sprintf("%d", e)
}
To demonstrate, check out this implementation:
http://play.golang.org/p/9NO6Lcdsbq
Just to clarify (because my use of the word "alias" may be misleading), two types which are otherwise equivalent (for example, int
and errorCode
in the above example) are not interchangeable. The Go type system treats them as fundamentally different types, although you may be able to type-cast between them.
答案2
得分: 3
要识别一组特定的值和操作。
例如,
package main
import "fmt"
type Coordinate float64
type Point struct {
x, y Coordinate
}
func (p *Point) Move(dx, dy Coordinate) {
p.x += dx
p.y += dy
}
func main() {
var p = Point{3.14159, 2.718}
fmt.Println(p)
p.Move(-1, +1)
fmt.Println(p)
}
输出:
{3.14159 2.718}
{2.14159 3.718}
英文:
> The Go Programming Language Specification
>
> Types
>
> A type determines the set of values and operations specific to values
> of that type.
You want identify a specific set of values and operations.
For example,
package main
import "fmt"
type Coordinate float64
type Point struct {
x, y Coordinate
}
func (p *Point) Move(dx, dy Coordinate) {
p.x += dx
p.y += dy
}
func main() {
var p = Point{3.14159, 2.718}
fmt.Println(p)
p.Move(-1, +1)
fmt.Println(p)
}
Output:
{3.14159 2.718}
{2.14159 3.718}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论