前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >寻龙分金看缠山,三行代码三重关

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

作者头像
后端时光
发布2022-12-19 21:49:25
2820
发布2022-12-19 21:49:25
举报
文章被收录于专栏:后端时光

最近看到一个文章,很有意思,代码虽简单,但考察内容却不少,话不多说,no bb,show me the code, 以下代码输出什么,心中默念一下答案,先不要着急回答。

代码语言:javascript
复制
// 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种类型都称为数值类型(整型、浮点数型和复数型)。

字面量和变量的区别

代码语言:javascript
复制
func test() string {
    return "测试字符串"
}

func main() {
    bar := test()
    fmt.Println(&bar)
}

如果换成这样

代码语言:javascript
复制
func test() string {
    return "test"
}

func main() {
    fmt.Println(&test())
}

运行后发现会报错,提示 "cannot take the address of test()"

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

什么叫可寻址?

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

代码语言:javascript
复制
func main() {
    test := "test"
 //0xc000116050
    fmt.Println(&test) 
}

哪些可寻址

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

变量

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

指针:&*x

代码语言:javascript
复制
type Test struct {
    Name string
}

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

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

代码语言:javascript
复制
s := [...]int{1,2,3}
fmt.Println(&s[0])
// output: xc0000b4010

切片

代码语言:javascript
复制
func main() {
    fmt.Println([]int{1, 2, 3}[1:])
}

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

代码语言:javascript
复制
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后对內建定义类型使用了新的写法:

代码语言:javascript
复制
type NewName = Type

这个NewName只是Type的别名。NewName和Type是一致的类型。

具体例子:

代码语言:javascript
复制
type intalias = int

而类型定义,则是会产生新的类型。虽然新类型和旧类型是一样的类型。但会被认为是不同的类型名字

代码语言:javascript
复制
type NewName Type

Go中有两种内置类型别名(type alias):

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

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

代码语言:javascript
复制
type rune = int32

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

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

总结

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

参考链接:https://baijiahao.baidu.com/s?id=1696452063970034305

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-09-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 后端时光 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是字面量
  • 字面量和变量的区别
  • 什么叫可寻址?
  • 哪些可寻址
    • 变量
      • 指针:&*x
        • 数组元素索引: &a[0]
          • 切片
            • 组合字面量: &struct{X type}{value}
            • 不同类型
            • 类型别名
            • 总结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档