rune 是 Go 语言的内建类型,它也是 int32 的别称。在 Go 语言中,rune 表示一个代码点。代码点无论占用多少个字节,都可以用一个 rune 来表示。
1 2 3 4 5 6 7 8 9 10
s := "Señor" for i:= 0; i < len(s); i++ { fmt.Printf("%c ",s[i]) // 打印出错,S e à ± o r } fmt.Printf("\n")
runes := []rune(s) for i:= 0; i < len(runes); i++ { // 字符串被转化为一个 rune 切片 fmt.Printf("%c ",runes[i]) // 打印正确,S e ñ o r }
字符串的 for range 循环更简单。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
funcprintCharsAndBytes(s string) { for index, rune := range s { fmt.Printf("%c starts at byte %d\n", rune, index) } }
funcmain() { name := "Señor" printCharsAndBytes(name) } /* S starts at byte 0 e starts at byte 1 ñ starts at byte 2 // ñ 占了两个字节 o starts at byte 4 r starts at byte 5 */
指针是一种存储变量内存地址(Memory Address)的变量。例如,变量 b 的值为 156,而 b 的内存地址为 0x1040a124,变量 a 存储了 b 的地址。我们就称 a 指向了 b。
指针的声明:指针变量的类型为 *T,该指针指向一个 T 类型的变量。
& 操作符用于获取变量的地址。下面的程序把 b 的地址赋值给 *int 类型的 a。我们称 a 指向了 b。当我们打印 a 的值时,会打印出 b 的地址。
1 2 3 4 5 6
funcmain() { b := 255 var a *int = &b fmt.Printf("Type of a is %T\n", a) // *int fmt.Println("address of b is", a) // 0x1040a124 }
指针的零值(Zero Value)是 nil。声明变量 var b *int,此时 b == nil 为 true。
指针的解引用:指针的解引用可以获取指针所指向的变量的值。将 a 解引用的语法是 *a。
1 2 3 4 5 6 7 8
funcmain() { b := 255 a := &b fmt.Println("address of b is", a) // 0x1040a124 fmt.Println("value of b is", *a) // 255 *a++ // (*a)++ fmt.Println("new value of b is", b) // 256 }
向函数传递指针参数:
1 2 3 4 5 6 7 8 9 10 11
funcchange(val *int) { *val = 55 }
funcmain() { a := 58 fmt.Println("value of a before function call is", a) // 58 b := &a change(b) fmt.Println("value of a after function call is", a) // 55 }
假如我们想要在函数内修改一个数组,并希望调用函数的地方也能得到修改后的数组,一种解决方案是把一个指向数组的指针传递给这个函数(但 Go 语言习惯的方法是用切片处理,见序号 7)。
1 2 3 4 5 6 7 8 9
funcmodify(arr *[3]int) { (*arr)[0] = 90 }
funcmain() { a := [3]int{89, 90, 91} modify(&a) fmt.Println(a) }