函数调用、赋值和Go中的“底层类型”

huangapple go评论76阅读模式
英文:

Function calls, assignment, and 'underlying types' in Go

问题

我正在学习Go语言(到目前为止我很喜欢),但是我遇到了一个有趣的问题。无法编译的代码如下:

package main

import "fmt"

type MyInt int

func (i MyInt) Double() MyInt {
    return i + i
}

func AddTwo(i int) int {
    return i + 2
}

func main() {
    var a int = 3
    var x MyInt = a  // 为什么这里会失败?
    fmt.Println(x.Double())
    var y int = AddTwo(x)  // 为什么这里会失败?
    fmt.Println(y)
}

这是Go Playground的链接:MyInt

当我尝试运行这段代码时,我得到了以下错误:

prog.go:17: cannot use a (type int) as type MyInt in assignment
prog.go:19: cannot use x (type MyInt) as type int in argument to AddTwo

然而,如果我正确理解规范的话,这段代码应该是可以编译的。首先,根据这个部分MyInt的底层类型是int。实际上,其中一个给出的例子是type T1 string,它说T1的底层类型是string。那么为什么我不能将a赋值给x呢?它们的底层类型不是相同的吗?对于对AddTwo()的函数调用也是一样的。x的底层类型不是int吗?为什么我不能将其作为int参数使用?

另外,为什么Double()能够编译通过呢?在表达式i + i中,我正在将两个MyInt值相加。它能够编译通过意味着MyInt至少在某种程度上是int类型。

总之,我有点困惑。所以我认为type MyInt int这样的声明的目的是为了能够给基本类型添加方法。但是如果失去了将它们视为int的能力(需要进行类型转换),那么整个“底层类型”的概念还有什么意义呢?

英文:

I'm learning Go (like it so far) but I've run into an interesting problem. The code that fails to compile is:

package main

import "fmt"

type MyInt int

func (i MyInt) Double() MyInt {
    return i + i
}

func AddTwo(i int) int {
	return i + 2
}

func main() {
    var a int = 3
    var x MyInt = a  // Why does this fail?
	fmt.Println(x.Double())
	var y int = AddTwo(x)  // Why does this fail?
	fmt.Println(y)
}

Here's the Go Playground link: MyInt

When I try to run this, I get the following errors:

  prog.go:17: cannot use a (type int) as type MyInt in assignment
  prog.go:19: cannot use x (type MyInt) as type int in argument to AddTwo

However, if I'm reading the spec correctly, this code should compile. First of all, the underlying type of MyInt is int according to this section. In fact, one of the examples given is type T1 string and it says the underlying type of T1 is string. So why can't I assign a to x? Don't they have the same underlying type? Same goes for the function call to AddTwo(). Isn't x has the underlying type int? Why can't I use it as an int argument?

Also, how come Double() compiles at all? In the expression i + i I'm adding two MyInt values. The fact that it compiles suggests that MyInt is an int at least in some sense.

Anyhow, I'm a bit confused. So I thought the point of declarations like type MyInt int was that now you can add methods to primitive types. But if you lose the ability to treat them as int (needing to cast), then what's the point of having this whole 'underlying type' business?

答案1

得分: 4

Go有一个严格的类型系统。仅仅因为你的类型只是int的别名,并不意味着你可以自由地互换它们,你仍然需要进行类型转换。下面是你的main函数的一个可工作版本,这是在playground上的代码;https://play.golang.org/p/kdVY145lrJ

func main() {
    var a int = 3
    var x MyInt = MyInt(a)  // 为什么这会失败?
    fmt.Println(x.Double())
    var y int = AddTwo(int(x))  // 为什么这会失败?
    fmt.Println(y)
}
英文:

Go has a strict type system. Just because your type is merely an alias for int doesn't mean you can interchange the two freely, you'll still have to do a type conversion. Below is a working version of your main, here's the code on play ground; https://play.golang.org/p/kdVY145lrJ

func main() {
    var a int = 3
    var x MyInt = MyInt(a)  // Why does this fail?
    fmt.Println(x.Double())
    var y int = AddTwo(int(x))  // Why does this fail?
    fmt.Println(y)
}

huangapple
  • 本文由 发表于 2015年10月29日 05:43:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/33402126.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定