Go:什么是字面量和组合字面量?

系统
说出来不怕大家笑话,在去年年初我刚开始学习 Go 基础的时候,有一个词困扰了我好久,这个词就是 字面量。

[[427693]]

# 0. 前言

说出来不怕大家笑话,在去年年初我刚开始学习 Go 基础的时候,有一个词困扰了我好久,这个词就是 字面量。

之所以会让我理解困难,是因为在 Go 之前,我都是写 Python 的,而且写了很多年,在 Python 中万物皆对象,不管一个字面量)有没有变量名来承接,在使用上没有任何区别的,因此在学 Go 之前,我其实都不知道有字面量这么个概念。

  1. >>> {"name""iswbm"}.get("name")  # 使用字面量 
  2. 'iswbm' 
  3. >>> 
  4. >>> profile={"name""iswbm"}   # 使用变量名 
  5. >>> profile.get("name"
  6. 'iswbm' 

那么字面量到底是啥东西?怎么那么多的基础教程里反复会提及,却好像没什么人把这个名词的概念解释一下呢?难道是因为这是常识?尴尬。。

相信正在看这篇文章的你,可能也会有此疑问,今天我就梳理一下,我理解中的 字面量,是什么意思?它与普通变量有什么区别?

# 1. 什么是字面量?

在 Go 中内置的基本类型有:

  • 布尔类型:bool
  • 11个内置的整数数字类型:int8, uint8, int16, uint16, int32, uint32, int64, uint64, int, uint和uintptr
  • 浮点数类型:float32和float64
  • 复数类型:complex64和complex128
  • 字符串类型:string

而这些基本类型值的文本,就是基本类型字面量。

比如下面这两个字符串,都是字符串字面量,没有用变量名或者常量名来指向这两个字面量,因此也称之为 未命名常量。

  1. "hello, iswbm" 
  2.  
  3. `hello, 
  4. iswbm` 

# 2. 同值不同字面量

值的字面量(literal)是代码中值的文字表示,一个值可能存在多种字面量表示。

举个例子,十进制的数值 15,可以由三种字面量表示

  1. // 16进制 
  2. 0xF 
  3.  
  4. // 8进制 
  5. 0o17 
  6.  
  7. // 2进制 
  8. 0b1111 

通过比较,可以看出他们是相等的

  1. import "fmt" 
  2.  
  3. func main() { 
  4.     fmt.Println(15 == 0xF)     // true 
  5.     fmt.Println(15 == 017)     // true 
  6.     fmt.Println(15 == 0b1111)  // true 

# 3. 字面量和变量有啥区别?

下面这是一段很正常的代码

  1. func foo() string { 
  2.     return "hello" 
  3.  
  4. func main() { 
  5.     bar := foo() 
  6.     fmt.Println(&bar) 

可要是换成下面这样

  1. func foo() string { 
  2.     return "hello" 
  3.  
  4. func main() { 
  5.     fmt.Println(&foo()) 

可实际上这段代码是有问题的,运行后会报错

  1. ./demo.go:11:14: cannot take the address of foo() 

你一定觉得很奇怪吧?

为什么先用变量名承接一下再取地址就不会报错,而直接使用在函数返回后的值上取地址就不行呢?

这是因为,如果不使用一个变量名承接一下,函数返回的是一个字符串的文本值,也就是字符串字面量,而这种基本类型的字面量是不可寻址的。

要想使用 & 进行寻址,就必须得用变量名承接一下。

# 4. 什么是组合字面量?

首先看下Go文档中对组合字面量(Composite Literal)的定义:

Composite literals construct values for structs, arrays, slices, and maps and create a new value each time they are evaluated. They consist of the type of the literal followed by a brace-bound list of elements. Each element may optionally be preceded by a corresponding key。

翻译成中文大致如下:组合字面量是为结构体、数组、切片和map构造值,并且每次都会创建新值。它们由字面量的类型后紧跟大括号及元素列表。每个元素前面可以选择性的带一个相关key。

什么意思呢?所谓的组合字面量其实就是把对象的定义和初始化放在一起了。

接下来让我们看看结构体、数组、切片和map各自的常规方式和组合字面量方式。

结构体的定义和初始化

让我们看一个struct结构体的常规的定义和初始化是怎么样的。

常规方式

常规方式这样定义是逐一字段赋值,这样就比较繁琐。

  1. type Profile struct { 
  2.     Name string 
  3.     Age int 
  4.     Gender string 
  5.  
  6. func main() { 
  7.     // 声明对象 
  8.     var xm Profile 
  9.  
  10.     // 属性赋值 
  11.     xm.Name = "iswbm" 
  12.     xm.Age = 18 
  13.     xm.Gender = "male" 

组合字面量方式

  1. type Profile struct {    Name string Age int Gender string}func main() { // 声明 + 属性赋值    xm := Profile{      Name:   "iswbm",        Age:    18,     Gender: "male", }} 

数组的定义和初始化

常规方式

在下面的代码中,我们在第1行定义了一个8个元素大小的字符串数组。然后一个一个的给元素赋值。即数组变量的定义和初始化是分开的。

  1. var planets [8]stringplanets[0] = "Mercury" //水星planets[1] = "Venus" //金星planets[2] = "Earth" //地球 

组合字面量方式

该示例中,就是将变量balls的定义和初始化合并了在一起。

  1. balls := [4]string{"basketball""football""Volleyball""Tennis"

slice的定义和初始化

常规方式

  1. // 第一种var s []string //定义切片变量s,s为默认零值nils = append(s, "hat""shirt") //往s中增加元素,len(s):2,cap(s):2// 第二种s := make([]string, 0, 10) //定义s,s的默认值不为零值 

组合字面量方式

由上面的常规方式可知,首先都是需要先定义切片,然后再往切片中添加元素。接下来我们看下组合字面量方式。

  1. s := []string{"hat""shirt"} //定义和初始化一步完成,自动计算切片的容量和长度 
  2. // or 
  3. var s = []string{"hat""shirt"

map的定义和初始化

常规方式

  1. //通过make函数初始化 
  2. m := make(map[string]int, 10) 
  3. m["english"] = 99 
  4. m["math"] = 98 

组合字面量方式

  1. m := map[string]int { 
  2.     "english": 99, 
  3.     "math": 98, 
  4.  
  5. //组合字面量初始化多维map 
  6. m2 := map[string]map[int]string { 
  7.     "english": { 
  8.         10: "english"
  9.     }, 

显然,使用组合字面量会比常规方式简单了不少。

# 5. 字面量的寻址问题

字面量,说白了就是未命名的常量,跟常量一样,他是不可寻址的。

这边以数组字面量为例进行说明

  1. func foo() [3]int { 
  2.     return [3]int{1, 2, 3} 
  3.  
  4. func main() { 
  5.     fmt.Println(&foo()) 
  6.     // cannot take the address of foo() 

关于寻址性的内容,你可以在我的上一篇文章中(Go 面试题 008:Go 中的可寻址和不可寻址怎么理解?)进行学习,总结得非常详细。

是不是很简单?跟着明哥一起来攻克 Go 的各个边边角角的知识吧

加油噢,我们下篇见

本文转载自微信公众号「Go编程时光」,可以通过以下二维码关注。转载本文请联系Go编程时光公众号。

 

责任编辑:武晓燕 来源: Go编程时光
相关推荐

2020-03-31 16:30:09

JS语言ES 6

2020-04-02 09:01:54

JSES 6开发

2022-06-08 08:01:28

模板字面量类型

2009-07-06 14:42:24

Visual Basi

2020-12-18 11:35:22

TypeScript语言Java

2023-09-20 00:02:33

C++14二进制字面量

2021-04-07 20:01:23

Go变量常量

2021-06-09 07:55:18

Python格式化字符串

2023-12-13 10:26:38

物联网数据控制系统

2018-02-23 15:10:07

轻量应用服务器

2011-06-19 12:12:12

网站浏览量访问量

2022-05-10 14:17:26

加密货币供应量以太坊

2022-05-10 11:32:12

加密货币比特币供应限制

2016-05-12 10:01:40

YunOS

2021-03-25 12:00:18

Python变量常量

2023-07-27 18:33:08

Go薪资JS

2021-08-30 08:03:22

信号量Go

2021-04-14 08:00:00

LinuxMXLinux计算机

2023-11-07 15:11:46

Kafka技巧

2011-10-25 14:45:19

AndroidiOS应用
点赞
收藏

51CTO技术栈公众号