字面值和组合字面值

基础类型字面量

一个值的字面形式称为一个字面量,它表示此值在代码中 文字体现形式(和内存中的表现形式相对应)。一个值可能会有很多种字面量形式。

未命名的字面量是不可寻址的

func foo() string { 
    return "hello" 
} 
 
func main() { 
    fmt.Println(&foo())  // cannot take the address of foo() 
} 

必须需要一个变量还接收字面量才行。

func foo() string { 
    return "hello" 
} 
 
func main() { 
    bar := foo() 
    fmt.Println(&bar) 
} 

整数类型值的字面量形式

整数类型值有四种字面量形式:十进制形式(decimal)、八进制形式(octal)、十六进制形式(hex)和二进制形式(binary)。 比如,下面的三个字面量均表示十进制的15:

0xF // 十六进制表示(必须使用0x或者0X开头)
0XF

017 // 八进制表示(必须使用0、0o或者0O开头)
0o17
0O17

0b1111 // 二进制表示(必须使用0b或者0B开头)
0B1111

15  // 十进制表示(必须不能用0开头)

字符串值的字面量形式

在Go中,字符串值是UTF-8编码的, 甚至所有的Go源代码都必须是UTF-8编码的。

Go字符串的字面量形式有两种。 一种是解释型字面表示(interpreted string literal,双引号风格)。 另一种是直白字面表示(raw string literal,反引号风格)。 下面的两个字符串表示形式是等价的:

// 解释形式
"Hello\nworld!\n\"你好世界\""

// 直白形式
`Hello
world!
"你好世界"`

浮点数类型值的字面量形式

一个浮点数的完整十进制字面量形式可能包含一个十进制整数部分、一个小数点、一个十进制小数部分和一个以10为底数的整数指数部分。 整数指数部分由字母e或者E带一个十进制的整数字面量组成(xEn表示x乘以10n的意思,而xE-n表示x除以10n的意思)。 常常地,某些部分可以根据情况省略掉。一些例子:

1.23
01.23 // == 1.23
.23
1.
// 一个e或者E随后的数值是指数值(底数为10)。
// 指数值必须为一个可以带符号的十进制整数字面量。
1.23e2  // == 123.0
123E2   // == 12300.0
123.E+2 // == 12300.0
1e-1    // == 0.1
.1e0    // == 0.1
0010e-2 // == 0.1
0e+5    // == 0.0

从Go 1.13开始,Go也支持另一种浮点数字面量形式:十六进制浮点数字面量。 在一个十六进制浮点数字面量中,

  • 一个十六进制浮点数字面量必须以一个以2为底数的整数指数部分。 这样的一个整数指数部分由字母p或者P带一个十进制的整数字面量组成(yPn表示y乘以2n的意思,而yP-n表示y除以2n的意思)。
  • 和整数的十六进制字面量一样,一个十六进制浮点数字面量也必须使用0x或者0X开头。 和整数的十六进制字面量不同的是,一个十六进制浮点数字面量可以包括一个小数点和一个十六进制小数部分。
0x1p-2     // == 1.0/4 = 0.25
0x2.p10    // == 2.0 * 1024 == 2048.0
0x1.Fp+0   // == 1+15.0/16 == 1.9375
0X.8p1     // == 8.0/16 * 2 == 1.0
0X1FFFP-16 // == 0.1249847412109375

虚部字面量形式

一个虚部值的字面量形式由一个浮点数字面量或者一个整数字面量和其后跟随的一个小写的字母i组成。 在Go 1.13之前,如果虚部中i前的部分为一个整数字面量,则其必须为并且总是被视为十进制形式。 一些例子:

1.23i
1.i
.23i
123i
0123i   // == 123i(兼容性使然。见下)
1.23E2i // == 123i
1e-1i
011i   // == 11i(兼容性使然。见下)
00011i // == 11i(兼容性使然。见下)
// 下面这几行从Go 1.13开始才能编译通过。
0o11i    // == 9i
0x11i    // == 17i
0b11i    // == 3i
0X.8p-0i // == 0.5i

数值字面表示中使用下划线分段来增强可读性

从Go 1.13开始,下划线_可以出现在整数、浮点数和虚部数字面量中,以用做分段符以增强可读性。 但是要注意,在一个数值字面表示中,一个下划线_不能出现在此字面表示的首尾,并且其两侧的字符必须为(相应进制的)数字字符或者进制表示头。

// 合法的使用下划线的例子
6_9          // == 69
0_33_77_22   // == 0337722
0x_Bad_Face  // == 0xBadFace
0X_1F_FFP-16 // == 0X1FFFP-16
0b1011_0111 + 0xA_B.Fp2i

// 非法的使用下划线的例子
_69        // 下划线不能出现在首尾
69_        // 下划线不能出现在首尾
6__9       // 下划线不能相连
0_xBadFace // x不是一个合法的八进制数字
1_.5       // .不是一个合法的十进制数字
1._5       // .不是一个合法的十进制数字

布尔值字面量

Go白皮书没有定义布尔类型值字面量形式。 我们可以将false和true这两个预声明的具名常量当作布尔类型的字面量形式。 但是,我们应该知道,从严格意义上说,它们不属于字面量。

组合字面量

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。

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

type Profile struct {
    Name string
    Age int
    Gender string
}

func main() {
    // 以字面量形式定义和初始化结构体
    xm := Profile{
        Name:   "iswbm",
        Age:    18,
        Gender: "male",
    }

   // 以字面量形式定义和初始化字符串数组
    balls := [4]string{"basketball", "football", "Volleyball", "Tennis"}
	
    // 以字面量形式定义和初始化字符串切片
	hobits := []string{"basketball", "football", "Volleyball", "Tennis"}

    // 以字面量形式定义和初始化map
    m := map[string]int {
        "english": 99,
        "math": 98,
    }
}