Golang的字面量
原文地址:https://juejin.cn/post/7077810136651300901/
在之前一篇文章Golang的寻址与不可寻址 我们有个结论:字面量都是不可寻址的。
但是什么是字面量呢?
什么是字面量
在 Go 中内置的基本类型有:
- 布尔类型:
bool
- 11个内置的整数数字类型:
int8
,uint8
,int16
,uint16
,int32
,uint32
,int64
,uint64
,int
,uint
和uintptr
- 浮点数类型:
float32
和float64
- 复数类型:
complex64
和complex128
- 字符串类型:
string
而这些基本类型值的文本,就是基本类型字面量。
比如下面这两个字符串,都是字符串字面量,没有用变量名或者常量名来指向这两个字面量,因此也称之为 未命名常量。
"hello, iswbm"
`hello,iswbm`
复制代码
字面量和变量有啥区别
先看一段代码
func foo() string {
return "yif"
}
func main() {
bar := foo()
fmt.Println(&bar) //0xc00003c1f0
}
复制代码
如果使用下面代码就报错:
func foo() string {
return "yif"
}
func main() {
fmt.Println(&foo()) //cannot take the address of foo()
}
复制代码
为什么先用变量名承接一下再取地址就不会报错,而直接使用在函数返回后的值上取地址就不行呢?
这是因为,如果不使用一个变量名承接一下,函数返回的是一个字符串的文本值,也就是字符串字面量,而这种基本类型的字面量是不可寻址的。
要想使用 &
进行寻址,就必须得用变量名承接一下。
什么是组合字面量
首先看下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各自的常规方式和组合字面量方式。
结构体的定义和初始化
常规方式
常规方式这样定义是逐一字段赋值,这样就比较繁琐
func main() {
// 声明对象
var p person
// 属性赋值
p.name = "yif"
p.age = 20
}
type person struct {
name string
age int
}
复制代码
组合字面量方式
func main() {
// 声明 + 属性赋值
p := person{
name: "yif",
age: 20,
}
fmt.Println(p)
}
type person struct {
name string
age int
}
复制代码
数组的定义和初始化
常规方式
一个一个的给元素赋值。即数组变量的定义和初始化是分开的
func main() {
var nameArr [3]string
nameArr[0] = "yif"
nameArr[1] = "tom"
nameArr[2] = "jim"
fmt.Println(nameArr)
}
复制代码
组合字面量方式
该示例中,就是将变量nameArr的定义和初始化合并了在一起
func main() {
nameArr := [3]string{"yif", "tom", "jim"}
fmt.Println(nameArr)
}
复制代码
slice的定义和初始化
常规方式
func main() {
// 第一种
var s []string //定义切片变量s,s为默认零值nil
s = append(s, "hat", "shirt") //往s中增加元素
fmt.Println(s)
// 第二种
s2 := make([]string, 0, 10) //定义s,s的默认值不为零值
fmt.Println(s2)
}
复制代码
组合字面量方式
由上面的常规方式可知,首先都是需要先定义切片,然后再往切片中添加元素。接下来我们看下组合字面量方式。
func main() {
s := []string{"yif", "tom"} //定义和初始化一步完成,自动计算切片的容量和长度
fmt.Println(s)
}
复制代码
map的定义和初始化
常规方式
func main() {
//通过make函数初始化
m := make(map[string]int, 10)
m["english"] = 99
m["math"] = 98
fmt.Println(m)
}
复制代码
组合字面量方式
func main() {
m := map[string]int{
"english": 99,
"math": 98,
}
fmt.Println(m)
}
复制代码
字面量的寻址问题
字面量,说白了就是未命名的常量,跟常量一样,他是不可寻址的。
这边以数组字面量为例进行说明
func foo() [3]int {
return [3]int{1, 2, 3}
}
func main() {
fmt.Println(&foo()) // cannot take the address of foo()
}
复制代码