最近看到一个文章,很有意思,代码虽简单,但考察内容却不少,话不多说,no bb,show me the code, 以下代码输出什么,心中默念一下答案,先不要着急回答。
// 32 位机器
var x int32 = 23.0
var y int = x
var z rune = x
在 Go 语言中,字面量是无类型(untyped)的。无类型是什么意思?无类型意味着可以赋值给类似类型的变量或常量
在 Go 中内置的基本类型有:
布尔类型:bool
11个内置的整数数字类型:int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint, uintptr
浮点数类型:float32, float64
复数类型:complex64, complex128
字符串类型:string
而这些基本类型值的文本,就是基本类型字面量。注意:除了 bool 和 string 类型,其它的15种类型都称为数值类型(整型、浮点数型和复数型)。
func test() string {
return "测试字符串"
}
func main() {
bar := test()
fmt.Println(&bar)
}
如果换成这样
func test() string {
return "test"
}
func main() {
fmt.Println(&test())
}
运行后发现会报错,提示 "cannot take the address of test()"
原因就是,test方法返回的是一个字符串值,也就是上面提到的字符串类型字面量。而字面量是不可寻址的,要想使用 & 进行寻址,就必须得用变量名承接一下。
可直接使用 & 操作符取地址的对象,就是可寻址的(Addressable)。举个栗子
func main() {
test := "test"
//0xc000116050
fmt.Println(&test)
}
那哪些类型可寻址呢?听我一一道来
就不给出例子了,可以参考上面的代码
type Test struct {
Name string
}
func main() {
fmt.Println(unsafe.Pointer(&Test{Name: "test"}))
// output: 0xc000108040
}
s := [...]int{1,2,3}
fmt.Println(&s[0])
// output: xc0000b4010
func main() {
fmt.Println([]int{1, 2, 3}[1:])
}
type Test struct {
Name string
}
func new() Test {
return Test{Name: "姓名"}
}
func main() {
// cannot take the address of new()
fmt.Println(&new())
}
注意上面写法与这个写法的区别,下面这个写法代表不同意思,其中的 & 并不是取地址的操作,而代表实例化一个结构体的指针。
在目前 Go 最新版本当中,int 类型在 32 位机器占 4 字节,64 位机器占 8 字节。所以在 32 位机器上,int32 和 int 的内存占用和内存布局是完全一样的。但 Go 语言不会做隐式类型转换,int 和 int32 是不同的类型,因此上题中 2)编译不通过。
GoLang1.9后对內建定义类型使用了新的写法:
type NewName = Type
这个NewName只是Type的别名。NewName和Type是一致的类型。
具体例子:
type intalias = int
而类型定义,则是会产生新的类型。虽然新类型和旧类型是一样的类型。但会被认为是不同的类型名字
type NewName Type
Go中有两种内置类型别名(type alias):
回到开头题目的 3),rune 是什么类型?定义如下:
type rune = int32
很显然,rune 是 int32 的别名,因此题目中 3)也能编译通过。
需要说明的是,在 Go1.9 之前,rune 和 byte 的别名性质就存在,是编译器负责处理的。只是 Go1.9 之后,别名可以用于其他类型了。
经过上面这么多的讲解、案例和对知识的思考,希望能够抛砖引玉,引起大家的讨论和一些思考,如果你觉得本文对你有一定的启发,引起了你的思考。 点赞、转发、收藏,下次你就能很快的找到我喽!
参考链接:https://baijiahao.baidu.com/s?id=1696452063970034305