笔记
字面量
整形字面量
为了便于阅读,允许使用下划线_
来进行数字划分,但是仅允许在前缀符号之后和数字之间使用。
24 // 24
024 // 24
2_4 // 24
0_2_4 // 24
10_000 // 10k
100_000 // 100k
0O24 // 20
0b00 // 0
0x00 // 0
0x0_0 // 0
浮点数字面量
通过不同的前缀可以表达不同进制的浮点数
0.
72.40
072.40 // == 72.40
2.71828
1.e+0
6.67428e-11
1E6
.25
.12345E+5
1_5. // == 15.0
0.15e+0_2 // == 15.0
0x1p-2 // == 0.25
0x2.p10 // == 2048.0
0x1.Fp+0 // == 1.9375
0X.8p-0 // == 0.5
0X_1FFFP-16 // == 0.1249847412109375
0x15e-2 // == 0x15e - 2 (integer subtraction)
#复数字面量">#复数字面量
0i
0123i // == 123i
0o123i // == 0o123 * 1i == 83i
0xabci // == 0xabc * 1i == 2748i
0.i
2.71828i
1.e+0i
6.67428e-11i
1E6i
.25i
.12345E+5i
0x1p-2i // == 0x1p-2 * 1i == 0.25i
#字符字面量">#字符字面量
字符字面量必须使用单引号括起来''
,Go中的字符完全兼容utf8
。
'a'
'ä'
'你'
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4'
'\U00101234'
#转义字符">#转义字符
Go中可用的转义字符
\a U+0007 响铃符号(建议调高音量)
\b U+0008 回退符号
\f U+000C 换页符号
\n U+000A 换行符号
\r U+000D 回车符号
\t U+0009 横向制表符号
\v U+000B 纵向制表符号
\\ U+005C 反斜杠转义
\' U+0027 单引号转义 (该转义仅在字符内有效)
\" U+0022 双引号转义 (该转义仅在字符串内有效)
#字符串字面量">#字符串字面量
字符串字面量必须使用双引号""
括起来或者反引号(反引号字符串不允许转义)
`abc` // "abc"
`\n
\n` // "\\n\n\\n"
"\n"
"\"" // `"`
"Hello, world!\n"
"今天天气不错"
"日本語"
"\u65e5本\U00008a9e"
"\xff\u00FF"
格式化
Go中的格式化输出功能基本上由fmt.Printf
函数提供,如果你学过C系语言,一定会觉得很熟悉,下面是一个简单的例子。
func main() {
fmt.Printf("hello world, %s!", "jack")
}
下面是Go目前所有的格式化动词。
使用fmt.Sprintf
或者fmt.Printf
来格式化字符串或者输出格式化字符串,看几个例子
fmt.Printf("%%%s\n", "hello world")
fmt.Printf("%s\n", "hello world")
fmt.Printf("%q\n", "hello world")
fmt.Printf("%d\n", 2<<7-1)
fmt.Printf("%f\n", 1e2)
fmt.Printf("%e\n", 1e2)
fmt.Printf("%E\n", 1e2)
fmt.Printf("%g\n", 1e2)
fmt.Printf("%b\n", 2<<7-1)
fmt.Printf("%#b\n", 2<<7-1)
fmt.Printf("%o\n", 2<<7-1)
fmt.Printf("%#o\n", 2<<7-1)
fmt.Printf("%x\n", 2<<7-1)
fmt.Printf("%#x\n", 2<<7-1)
fmt.Printf("%X\n", 2<<7-1)
fmt.Printf("%#X\n", 2<<7-1)
type person struct {
name string
age int
address string
}
fmt.Printf("%v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%+v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%#v\n", person{"lihua", 22, "beijing"})
fmt.Printf("%t\n", true)
fmt.Printf("%T\n", person{})
fmt.Printf("%c%c\n", 20050, 20051)
fmt.Printf("%U\n", '码')
fmt.Printf("%p\n", &person{})
使用其它进制时,在%
与格式化动词之间加上一个空格便可以达到分隔符的效果,例如
func main() {
str := "abcdefg"
fmt.Printf("%x\n", str)
fmt.Printf("% x\n", str)
}
该例输出的结果为
61626364656667
61 62 63 64 65 66 67
在使用数字时,还可以自动补零。比如
fmt.Printf("%09d", 1)
// 000000001
二进制同理
fmt.Printf("%09b", 1<<3)
// 000001000
错误情况
格式化字符数量 < 参数列表数量
fmt.Printf("", "") //%!(EXTRA string=)
格式化字符数量 > 参数列表数量
fmt.Printf("%s%s", "") //%!s(MISSING)
类型不匹配
fmt.Printf("%s", 1) //%!s(int=1)
缺少格式化动词
fmt.Printf("%", 1) // %!(NOVERB)%!(EXTRA int=1)
数组与切片
数组的切割得到的切片和数组指向同一片内存,如果需要深度克隆使用以下方法
func main() {
arr := [5]int{1, 2, 3, 4, 5}
slice := slices.Clone(arr[:])
slice[0] = 0
fmt.Printf("array: %v\n", arr)
fmt.Printf("slice: %v\n", slice)
}
...(语法糖)
‘…’ 其实是go的一种语法糖。
它的第一个用法主要是用于函数有多个不定参数的情况,可以接受多个不确定数量的参数。
第二个用法是slice可以被打散进行传递。
下面直接上例子:
func test1(args ...string) { //可以接受任意个string参数
for _, v:= range args{
fmt.Println(v)
}
}
func main(){
var strss= []string{
"qwr",
"234",
"yui",
"cvbc",
}
test1(strss...) //切片被打散传入
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
结果:
qwr
234
yui
cvbc
1
2
3
4
其中strss切片内部的元素数量可以是任意个,test1函数都能够接受。
第二个例子:
var strss= []string{
"qwr",
"234",
"yui",
}
var strss2= []string{
"qqq",
"aaa",
"zzz",
"zzz",
}
strss=append(strss,strss2...) //strss2的元素被打散一个个append进strss
fmt.Println(strss)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
结果:
[qwr 234 yui qqq aaa zzz zzz]
函数
Go语言不允许函数重载!
返回值
下面是一个简单的函数返回值的例子,Sum
函数返回一个int
类型的值。
func Sum(a, b int) int {
return a + b
}
当函数没有返回值时,不需要void
,不带返回值即可。
func ErrPrintf(format string, a ...any) {
_, _ = fmt.Fprintf(os.Stderr, format, a...)
}
Go允许函数有多个返回值,此时就需要用括号将返回值围起来。
func Div(a, b float64) (float64, error) {
if a == 0 {
return math.NaN(), errors.New("0不能作为被除数")
}
return a / b, nil
}
Go也支持具名返回值,不能与参数名重复,使用具名返回值时,return
关键字可以不需要指定返回哪些值。
func Sum(a, b int) (ans int) {
ans = a + b
return
}
和参数一样,当有多个同类型的具名返回值时,可以省略掉重复的类型声明
func SumAndMul(a, b int) (c, d int) {
c = a + b
d = a * b
return
}
不管具名返回值如何声明,永远都是以return
关键字后的值为最高优先级。
func SumAndMul(a, b int) (c, d int) {
c = a + b
d = a * b
// c,d将不会被返回
return a + b, a * b
}
匿名函数
匿名函数就是没有签名的函数,例如下面的函数func(a, b int) int
,它没有名称,所以我们只能在它的函数体后紧跟括号来进行调用。
func main() {
func(a, b int) int {
return a + b
}(1, 2)
}