%v,和%q是什么意思
%v
------ 默认格式("value" 的缩写)
作用:按值的默认格式输出,适用于任何类型。
代码示例:
fmt.Printf("%v\n", "Hello") // 输出: Hello
fmt.Printf("%v\n", 42) // 输出: 42
fmt.Printf("%v\n", true) // 输出: true
%q
------ 带引号的字符串("quoted" 的缩写)
作用:输出值的带引号字符串形式,适用于字符串、字节切片、rune
等。
代码示例:
fmt.Printf("%q\n", "Hello") // 输出: "Hello"(带双引号)
fmt.Printf("%q\n", 'A') // 输出: 'A'(单引号,rune 类型)
fmt.Printf("%q\n", 65) // 输出: 'A'(ASCII 码 65 对应的字符)
fmt.Printf("%q\n", "\n") // 输出: "\n"(转义为可见形式)
:=
vs var
vs =适用场景
语法 | 适用场景 | 示例 |
---|---|---|
:= |
局部变量声明 + 初始化(类型推断) | x := 10 |
var |
全局变量 / 显式指定类型 | var x int = 10 |
= |
变量赋值(不能用于声明) | x = 20 |
defer
关键字
用于延迟执行 函数调用。defer
语句会将函数调用推入一个栈中,在当前函数返回之前(无论是正常返回还是 panic 导致的异常返回),这些被延迟的函数调用会按照后进先出(LIFO)的顺序执行。
基本用法
func main() {
defer fmt.Println("这是第一个defer语句")
defer fmt.Println("这是第二个defer语句")
fmt.Println("主函数执行")
// 输出:
// 主函数执行
// 这是第二个defer语句
// 这是第一个defer语句
}
指针
Go 拥有指针。指针保存了值的内存地址。
类型 *T
是指向 T
类型值的指针,其零值为 nil
。
var p *int
&
操作符会生成一个指向其操作数的指针。
i := 42
p = &i
*
操作符表示指针指向的底层值。
fmt.Println(*p) // 通过指针 p 读取 i
*p = 21 // 通过指针 p 设置 i
这也就是通常所说的「解引用」或「间接引用」。
与 C 不同,Go 没有指针运算。
package main
import "fmt"
func main() {
i, j := 42, 2701
p := &i // 指向 i
fmt.Println(*p) // 通过指针读取 i 的值
*p = 21 // 通过指针设置 i 的值
fmt.Println(i) // 查看 i 的值
p = &j // 指向 j
*p = *p / 37 // 通过指针对 j 进行除法运算
fmt.Println(j) // 查看 j 的值
}
//输出:
//42
//21
//73
切片
切片是数组的视图,修改切片会影响底层数组。
多个切片可以共享底层数据,修改一个会影响其他。
如果需要独立副本,使用 copy
或 append
创建新切片。
package main
import "fmt"
func main() {
names := [4]string{
"John",
"Paul",
"George",
"Ringo",
}
fmt.Println(names)
a := names[0:2]
b := names[1:3]
fmt.Println(a, b)
b[0] = "XXX"
fmt.Println(a, b)
fmt.Println(names)
}
//输出:
//[John Paul George Ringo]
//[John Paul] [Paul George]
//[John XXX] [XXX George]
//[John XXX George Ringo]