您当前的位置:首页 > 计算机 > 编程开发 > Go语言

寻龙分金看缠山,三行代码三重关

时间:07-30来源:作者:点击数:

最近看到一个文章,很有意思,代码虽简单,但考察内容却不少,话不多说,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()”

image-20220906211246467

原因就是,test方法返回的是一个字符串值,也就是上面提到的字符串类型字面量。而字面量是不可寻址的,要想使用 & 进行寻址,就必须得用变量名承接一下。

什么叫可寻址?

可直接使用 & 操作符取地址的对象,就是可寻址的(Addressable)。举个栗子

func main() {
    test := "test"
	//0xc000116050
    fmt.Println(&test) 
}

哪些可寻址

那哪些类型可寻址呢?听我一一道来

变量

就不给出例子了,可以参考上面的代码

指针:&*x

type Test struct {
    Name string
}

func main() {
    fmt.Println(unsafe.Pointer(&Test{Name: "test"}))
    // output: 0xc000108040
}

数组元素索引: &a[0]

s := [...]int{1,2,3}
fmt.Println(&s[0])
// output: xc0000b4010

切片

func main() {
    fmt.Println([]int{1, 2, 3}[1:])
}

组合字面量: &struct{X type}{value}

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):

  • byte是uint8的内置别名。 我们可以将byte和uint8看作是同一个类型。
  • rune是int32的内置别名。 我们可以将rune和int32看作是同一个类型。

回到开头题目的 3),rune 是什么类型?定义如下:

type rune = int32

很显然,rune 是 int32 的别名,因此题目中 3)也能编译通过。

需要说明的是,在 Go1.9 之前,rune 和 byte 的别名性质就存在,是编译器负责处理的。只是 Go1.9 之后,别名可以用于其他类型了。

总结

经过上面这么多的讲解、案例和对知识的思考,希望能够抛砖引玉,引起大家的讨论和一些思考,如果你觉得本文对你有一定的启发,引起了你的思考。 点赞、转发、收藏,下次你就能很快的找到我喽!

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门