变量
goCopy code
package main
import (
"fmt"
"math"
)
func main() {
// 声明并初始化变量
var a = "initial"
// 声明并初始化多个变量
var b, c int = 1, 2
// 声明并初始化变量,并推断其类型
var d = true
// 声明变量,但没有初始化,Go 会自动赋予零值
var e float64
// 使用短声明方式,声明并初始化变量(类型推断)
f := float32(e)
// 字符串拼接
g := a + "foo"
fmt.Println(a, b, c, d, e, f) // 输出: initial 1 2 true 0 0
fmt.Println(g) // 输出: initialfoo
// 声明常量
const s string = "constant"
const h = 500000000
const i = 3e20 / h
// 输出常量和数学函数的计算结果
fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}
代码解释:
-
变量声明和初始化:
var a = "initial"
:声明一个名为a
的变量,初始值为字符串 "initial"。var b, c int = 1, 2
:声明两个整数变量b
和c
,并分别初始化为 1 和 2。var d = true
:声明一个布尔变量d
,初始值为true
。var e float64
:声明一个浮点数变量e
,因为没有显式初始化,所以会被赋予浮点数类型的零值 0.0。f := float32(e)
:使用短声明方式,声明并初始化变量f
,类型为float32
,值从变量e
转换而来。
-
字符串拼接:
g := a + "foo"
:使用+
运算符将字符串a
和 "foo" 进行拼接,结果存储在变量g
中。
-
输出:
fmt.Println(...)
:使用fmt.Println
函数输出多个值,以空格分隔。
-
常量声明和计算:
const s string = "constant"
:声明一个字符串常量s
,初始值为 "constant"。const h = 500000000
:声明一个整数常量h
,初始值为 500000000。const i = 3e20 / h
:声明一个浮点数常量i
,计算结果为3e20
(科学计数法表示的值)除以常量h
。
-
使用数学函数:
math.Sin(h)
和math.Sin(i)
:使用math
包中的Sin
函数分别计算h
和i
的正弦值。
for
goCopy code
package main
import "fmt"
func main() {
// 无限循环,直到遇到 break
i := 1
for {
fmt.Println("loop")
break
}
// 基本的 for 循环,从 7 到 8
for j := 7; j < 9; j++ {
fmt.Println(j)
}
// 使用 continue 跳过偶数
for n := 0; n < 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
}
// 使用 for 循环实现类似 while 的效果
for i <= 3 {
fmt.Println(i)
i = i + 1
}
}
代码解释:
for {...}
:这是一个无限循环,因为没有在循环条件中提供任何条件。在循环体内部,fmt.Println("loop")
输出字符串 "loop",然后通过break
语句跳出循环。这将导致循环仅迭代一次。for j := 7; j < 9; j++ {...}
:这是一个基本的for
循环,它从j
等于 7 开始,每次迭代增加j
的值,直到j
小于 9。在循环体内,fmt.Println(j)
打印当前j
的值。for n := 0; n < 5; n++ {...}
:这个for
循环在n
从 0 到 4 变化时迭代。在循环体内部,通过检查n%2 == 0
来判断n
是否为偶数,如果是偶数,那么continue
语句会跳过当前迭代,直接进行下一次迭代。这样,只有奇数会被打印出来。for i <= 3 {...}
:这个for
循环模拟了类似于while
的行为。当i
小于等于 3 时,循环会一直迭代。在每次迭代中,fmt.Println(i)
打印当前的i
值,然后通过i = i + 1
增加i
的值。
if
goCopy code
package main
import "fmt"
func main() {
// 检查奇偶性
if 7%2 == 0 {
fmt.Println("7 is even")
} else {
fmt.Println("7 is odd")
}
// 检查是否能被 4 整除
if 8%4 == 0 {
fmt.Println("8 is divisible by 4")
}
// 使用条件语句块进行条件判断和多分支
if num := 9; num < 0 {
fmt.Println(num, "is negative")
} else if num < 10 {
fmt.Println(num, "has 1 digit")
} else {
fmt.Println(num, "has multiple digits")
}
}
代码解释:
-
if condition { ... } else { ... }
:这是一个基本的if-else
语句结构。如果condition
为真(true),则执行位于{ ... }
内的代码块,否则执行位于else { ... }
内的代码块。 -
if 7%2 == 0 { ... } else { ... }
:这个条件判断语句检查 7 是否为偶数。由于 7 除以 2 的余数不为 0,所以执行else
块,输出 "7 is odd"。 -
if 8%4 == 0 { ... }
:这个条件判断语句检查 8 是否能被 4 整除。由于 8 能被 4 整除,所以输出 "8 is divisible by 4"。 -
if num := 9; num < 0 { ... } else if num < 10 { ... } else { ... }
:这个条件语句块演示了 Go 语言中的局部变量初始化。在if
语句的条件中,使用num := 9
初始化了一个局部变量num
。然后根据num
的值进行多分支判断:- 如果
num
小于 0,输出 "9 is negative"。 - 否则,如果
num
小于 10,输出 "9 has 1 digit"。 - 如果上述条件都不满足,则输出 "9 has multiple digits"。
- 如果
switch
goCopy code
package main
import (
"fmt"
"time"
)
func main() {
// 基本的 switch 语句,匹配不同的 case
a := 2
switch a {
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
case 4, 5:
fmt.Println("four or five")
default:
fmt.Println("other")
}
// 使用无条件表达式的 switch 语句,根据时间判断上午或下午
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
}
代码解释:
-
switch a { ... }
:这是一个基本的switch
语句结构。它根据变量a
的值,匹配不同的case
分支。在这个例子中,变量a
的值为 2,所以输出 "two"。 -
case 4, 5:
:这个case
分支匹配值为 4 或 5 的情况,输出 "four or five"。这里可以同时匹配多个值。 -
default:
:当没有任何case
分支匹配时,将执行default
分支,输出 "other"。 -
使用无条件表达式的
switch
语句:t := time.Now()
:使用time.Now()
获取当前时间。switch { ... }
:这个switch
语句没有在switch
关键字后面添加表达式。每个case
分支会根据条件判断是否匹配,条件在case
分支中的表达式中定义。t.Hour() < 12:
:这个条件判断检查当前时间的小时数是否小于 12。如果为真,执行第一个case
分支,输出 "It's before noon"。否则,执行default
分支,输出 "It's after noon"。
array
goCopy code
package main
import "fmt"
func main() {
// 声明一个长度为 5 的整数数组
var a [5]int
// 在数组的第 5 个位置赋值为 100
a[4] = 100
// 输出数组的第 2 个位置的值
fmt.Println("get:", a[2])
// 输出数组的长度
fmt.Println("len:", len(a))
// 声明并初始化一个包含 5 个整数的数组
b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)
// 声明一个 2x3 的整数数组
var twoD [2][3]int
// 使用循环为数组赋值
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("2d: ", twoD)
}
代码解释:
var a [5]int
:这是一个长度为 5 的整数数组的声明。在 Go 中,数组的长度也是其类型的一部分。a[4] = 100
:将数组a
的第 5 个元素(下标为 4)赋值为 100。fmt.Println("get:", a[2])
:输出数组a
中的第 3 个元素(下标为 2)的值。fmt.Println("len:", len(a))
:输出数组a
的长度,即 5。b := [5]int{1, 2, 3, 4, 5}
:使用数组字面值初始化一个包含 1 到 5 的整数数组。var twoD [2][3]int
:声明一个二维数组,其维度为 2x3。- 嵌套循环
for i := 0; i < 2; i++
和for j := 0; j < 3; j++
:使用嵌套循环为二维数组twoD
赋值,数组中的每个元素的值为其行数和列数之和。
slice
goCopy code
package main
import "fmt"
func main() {
// 使用 make 创建一个长度为 3 的字符串切片
s := make([]string, 3)
// 设置切片的元素值
s[0] = "a"
s[1] = "b"
s[2] = "c"
// 输出切片的第 3 个元素
fmt.Println("get:", s[2]) // 输出:c
// 输出切片的长度
fmt.Println("len:", len(s)) // 输出:3
// 使用 append 向切片中追加元素
s = append(s, "d")
s = append(s, "e", "f")
fmt.Println(s) // 输出:[a b c d e f]
// 使用 copy 复制切片
c := make([]string, len(s))
copy(c, s)
fmt.Println(c) // 输出:[a b c d e f]
// 使用切片操作获取部分切片
fmt.Println(s[2:5]) // 输出:[c d e]
fmt.Println(s[:5]) // 输出:[a b c d e]
fmt.Println(s[2:]) // 输出:[c d e f]
// 直接初始化切片
good := []string{"g", "o", "o", "d"}
fmt.Println(good) // 输出:[g o o d]
}
代码解释:
-
s := make([]string, 3)
:使用make
创建一个长度为 3 的字符串切片。 -
切片元素设置:
s[0] = "a"
:设置切片s
的第一个元素为字符串 "a"。s[1] = "b"
:设置切片s
的第二个元素为字符串 "b"。s[2] = "c"
:设置切片s
的第三个元素为字符串 "c"。
-
fmt.Println("get:", s[2])
:输出切片s
的第三个元素,即 "c"。 -
fmt.Println("len:", len(s))
:输出切片s
的长度,即 3。 -
使用
append
向切片追加元素:s = append(s, "d")
:追加字符串 "d" 到切片s
。s = append(s, "e", "f")
:同时追加字符串 "e" 和 "f" 到切片s
。
-
使用
copy
复制切片:c := make([]string, len(s))
:创建一个与切片s
长度相同的新切片c
。copy(c, s)
:将切片s
复制到切片c
。
-
切片操作:
s[2:5]
:从切片s
中获取索引从 2 到 4 的元素,即 "c", "d", "e"。s[:5]
:从切片s
中获取索引从 0 到 4 的元素,即 "a", "b", "c", "d", "e"。s[2:]
:从切片s
中获取索引从 2 开始到末尾的元素,即 "c", "d", "e", "f"。
-
直接初始化切片:
good := []string{"g", "o", "o", "d"}
:创建一个包含字符串的切片。
map
goCopy code
package main
import "fmt"
func main() {
// 使用 make 创建一个字符串到整数的映射
m := make(map[string]int)
// 将键值对添加到映射
m["one"] = 1
m["two"] = 2
// 输出映射的内容
fmt.Println(m) // 输出:map[one:1 two:2]
// 输出映射的长度
fmt.Println(len(m)) // 输出:2
// 输出指定键的值
fmt.Println(m["one"]) // 输出:1
// 输出未定义键的值,默认为 0
fmt.Println(m["unknown"]) // 输出:0
// 使用两个返回值检查映射中是否存在指定键
r, ok := m["unknown"]
fmt.Println(r, ok) // 输出:0 false
// 从映射中删除指定键的值
delete(m, "one")
// 直接初始化映射
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}
代码解释:
-
m := make(map[string]int)
:使用make
创建一个字符串到整数的映射。 -
添加键值对到映射:
m["one"] = 1
:将键 "one" 对应的值设为 1。m["two"] = 2
:将键 "two" 对应的值设为 2。
-
fmt.Println(m)
:输出映射的内容,结果为map[one:1 two:2]
。 -
fmt.Println(len(m))
:输出映射的长度,结果为 2。 -
fmt.Println(m["one"])
:输出映射中键 "one" 对应的值,结果为 1。 -
fmt.Println(m["unknown"])
:输出映射中未定义键 "unknown" 对应的值,默认为 0。 -
r, ok := m["unknown"]
:使用两个返回值检查映射中是否存在键 "unknown"。r
将会被赋值为该键的值(默认为 0),ok
将会被赋值为false
,表示未找到键 "unknown"。 -
delete(m, "one")
:从映射中删除键 "one" 及其对应的值。 -
直接初始化映射:
m2 := map[string]int{"one": 1, "two": 2}
:创建并初始化一个映射。var m3 = map[string]int{"one": 1, "two": 2}
:通过var
关键字声明并初始化映射。
range
goCopy code
package main
import "fmt"
func main() {
// 使用 range 迭代切片
nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // 输出:index: 0 num: 2
}
}
fmt.Println(sum) // 输出:9
// 使用 range 迭代映射
m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
fmt.Println(k, v) // 输出:b B; a A
}
// 使用 range 迭代映射的键
for k := range m {
fmt.Println("key", k) // 输出:key a; key b
}
}
代码解释
-
nums := []int{2, 3, 4}
:声明一个整数切片nums
,包含元素 2、3 和 4。 -
使用
range
迭代切片:for i, num := range nums { ... }
:使用range
关键字迭代切片nums
,i
是当前元素的索引,num
是当前元素的值。sum += num
:将切片中的每个元素值累加到sum
变量中。if num == 2 { ... }
:如果当前元素的值等于 2,输出索引和值。
-
fmt.Println(sum)
:输出sum
的值,即切片中所有元素的和,结果为 9。 -
使用
range
迭代映射:for k, v := range m { ... }
:使用range
关键字迭代映射m
,k
是当前键,v
是当前键对应的值。fmt.Println(k, v)
:输出映射中的键和值。
-
使用
range
迭代映射的键:for k := range m { ... }
:使用range
关键字迭代映射m
的键。fmt.Println("key", k)
:输出映射中的每个键。
func
goCopy code
package main
import "fmt"
// 定义一个接受两个整数参数并返回它们之和的函数
func add(a int, b int) int {
return a + b
}
// 可简化参数类型定义的函数
func add2(a, b int) int {
return a + b
}
// 定义一个函数用于检查映射中是否存在指定的键,并返回对应的值和是否存在的布尔值
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
// 调用 add 函数,计算 1 + 2
res := add(1, 2)
fmt.Println(res) // 输出:3
// 调用 exists 函数,检查映射中是否存在键 "a"
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok) // 输出:A true
}
代码解释:
goCopy code
package main
import "fmt"
// 定义一个接受两个整数参数并返回它们之和的函数
func add(a int, b int) int {
return a + b
}
// 可简化参数类型定义的函数
func add2(a, b int) int {
return a + b
}
// 定义一个函数用于检查映射中是否存在指定的键,并返回对应的值和是否存在的布尔值
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
// 调用 add 函数,计算 1 + 2
res := add(1, 2)
fmt.Println(res) // 输出:3
// 调用 exists 函数,检查映射中是否存在键 "a"
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok) // 输出:A true
}
func add(a int, b int) int { ... }
:这是一个定义函数add
的语句。该函数接受两个整数参数a
和b
,并返回它们的和。func add2(a, b int) int { ... }
:这是一个更简化的函数定义方式。参数类型可以在最后一个参数前进行简化。func exists(m map[string]string, k string) (v string, ok bool) { ... }
:这是定义函数exists
的语句。该函数接受一个映射m
和一个键k
,并返回键k
对应的值v
和一个布尔值ok
,表示键是否存在。- 在
main
函数中,通过调用add
函数,将 1 和 2 相加并输出结果。 - 在
main
函数中,通过调用exists
函数,检查映射map[string]string{"a": "A"}
是否存在键 "a",并输出键对应的值和布尔值。
pointer
goCopy code
package main
import "fmt"
// 传递一个整数值,但在函数内部对参数值进行修改不影响原始值
func add2(n int) {
n += 2
}
// 传递一个整数的指针,可以通过指针间接修改原始值
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2(n)
fmt.Println(n) // 输出:5,因为 add2 函数内部对参数值进行修改,不影响原始值
add2ptr(&n)
fmt.Println(n) // 输出:7,因为 add2ptr 函数接受指针参数,通过指针修改了原始值
}
代码解释:
func add2(n int) { ... }
:这是一个函数,接受一个整数值作为参数n
。在函数内部,对n
的修改不会影响传入的原始值,因为传递的是值的副本。func add2ptr(n *int) { ... }
:这是另一个函数,接受一个整数的指针作为参数n
。在函数内部,通过解引用指针*n
并对其进行修改,可以影响传入的原始值。- 在
main
函数中,声明变量n
并赋值为 5。 add2(n)
:调用add2
函数,并传递n
的值。这里传递的是值的副本,所以函数内部对参数n
的修改不会影响原始值。fmt.Println(n)
:输出n
的值,结果为 5,因为add2
函数内部的修改不影响原始值。add2ptr(&n)
:调用add2ptr
函数,并传递n
的地址(指针)。这里传递的是指针,所以函数内部对指针解引用并进行修改会影响原始值。fmt.Println(n)
:输出n
的值,结果为 7,因为add2ptr
函数通过指针修改了原始值。
struct
goCopy code
package main
import "fmt"
// 定义一个名为 user 的结构体类型,包含 name 和 password 字段
type user struct {
name string
password string
}
func main() {
// 使用不同方式初始化 user 结构体变量
a := user{name: "wang", password: "1024"}
b := user{"wang", "1024"}
c := user{name: "wang"}
c.password = "1024"
var d user
d.name = "wang"
d.password = "1024"
// 输出结构体变量的值
fmt.Println(a, b, c, d) // 输出:{wang 1024} {wang 1024} {wang 1024} {wang 1024}
// 调用 checkPassword 函数,检查密码是否匹配
fmt.Println(checkPassword(a, "haha")) // 输出:false
// 调用 checkPassword2 函数,通过指针传递结构体
fmt.Println(checkPassword2(&a, "haha")) // 输出:false
}
// 定义函数 checkPassword,接受结构体和密码作为参数,返回密码是否匹配
func checkPassword(u user, password string) bool {
return u.password == password
}
// 定义函数 checkPassword2,接受结构体指针和密码作为参数,返回密码是否匹配
func checkPassword2(u *user, password string) bool {
return u.password == password
}
代码解释:
-
type user struct { ... }
:这是定义结构体类型user
的语句。结构体类型包含两个字段:name
和password
。 -
使用不同的方式初始化
user
结构体变量:a := user{name: "wang", password: "1024"}
:通过字段名初始化结构体变量a
。b := user{"wang", "1024"}
:使用字段值的列表初始化结构体变量b
。c := user{name: "wang"}
:通过字段名初始化结构体变量c
的部分字段,然后单独设置其password
字段。var d user
:声明一个变量d
为零值的结构体,然后分别设置其字段的值。
-
fmt.Println(a, b, c, d)
:输出四个结构体变量的值。 -
checkPassword
函数:接受一个user
结构体值和一个密码字符串,检查密码是否匹配,并返回布尔值。 -
checkPassword2
函数:接受一个user
结构体指针和一个密码字符串,检查密码是否匹配,并返回布尔值。 -
在
main
函数中,调用checkPassword
函数,传递一个结构体值和密码,检查密码是否匹配,结果为false
。 -
在
main
函数中,调用checkPassword2
函数,传递一个结构体指针和密码,检查密码是否匹配,结果为false
。
struct-method
goCopy code
package main
import "fmt"
type user struct {
name string
password string
}
// 为 user 结构体定义一个方法 checkPassword,接收者为值类型 user
func (u user) checkPassword(password string) bool {
return u.password == password
}
// 为 user 结构体定义一个方法 resetPassword,接收者为指针类型 *user
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
// 创建一个 user 结构体变量 a
a := user{name: "wang", password: "1024"}
// 调用 resetPassword 方法,重置密码
a.resetPassword("2048")
// 调用 checkPassword 方法,检查密码是否匹配
fmt.Println(a.checkPassword("2048")) // 输出:true
}
代码解释:
type user struct { ... }
:这是定义结构体类型user
的语句。func (u user) checkPassword(password string) bool { ... }
:这是为结构体user
定义一个方法checkPassword
的语句。方法接收者为结构体值类型user
。该方法接受一个密码字符串作为参数,检查密码是否匹配,并返回布尔值。func (u *user) resetPassword(password string) { ... }
:这是为结构体user
定义另一个方法resetPassword
的语句。方法接收者为结构体指针类型*user
。该方法接受一个密码字符串作为参数,重置结构体中的密码字段。- 在
main
函数中,创建一个user
结构体变量a
,设置初始用户名和密码。 a.resetPassword("2048")
:调用resetPassword
方法,通过指针接收者修改了结构体变量a
的密码。fmt.Println(a.checkPassword("2048"))
:调用checkPassword
方法,检查密码是否匹配 "2048",输出结果为true
。
error
goCopy code
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
// 定义一个函数,查找指定名称的用户
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil // 返回找到的用户和没有错误
}
}
return nil, errors.New("not found") // 没有找到用户,返回错误
}
func main() {
// 在给定用户切片中查找 "wang"
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err) // 没有错误,输出为空
return
}
fmt.Println(u.name) // 输出:wang
// 在给定用户切片中查找 "li"
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err) // 输出:not found
return
} else {
fmt.Println(u.name) // 不会执行到这里
}
}
代码解释:
errors.New("not found")
:使用errors
包中的New
函数创建一个新的错误实例,内容为 "not found"。findUser
函数:接受用户切片和名称作为参数,遍历用户切片,如果找到与名称匹配的用户,则返回用户指针和没有错误;如果没有找到,则返回not found
错误。- 在
main
函数中,调用findUser
函数,传递用户切片和名称 "wang"。如果找到用户,将用户指针存储在u
中,如果未找到,将返回一个错误实例,存储在err
中。 - 使用
if err != nil
判断错误是否存在。如果存在错误,则输出错误内容。 - 在另一个
if
分支中,再次调用findUser
函数,查找名称 "li"。如果找到用户,将用户指针存储在u
中,如果未找到,将返回一个错误实例,存储在err
中。如果存在错误,输出错误内容为 "not found"。
string
goCopy code
package main
import (
"fmt"
"strings"
)
func main() {
a := "hello"
// 判断字符串是否包含子串
fmt.Println(strings.Contains(a, "ll")) // 输出:true
// 计算子串在字符串中出现的次数
fmt.Println(strings.Count(a, "l")) // 输出:2
// 判断字符串是否以指定前缀开头
fmt.Println(strings.HasPrefix(a, "he")) // 输出:true
// 判断字符串是否以指定后缀结尾
fmt.Println(strings.HasSuffix(a, "llo")) // 输出:true
// 返回子串在字符串中首次出现的索引
fmt.Println(strings.Index(a, "ll")) // 输出:2
// 将字符串切片用指定分隔符连接
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // 输出:he-llo
// 重复字符串指定次数
fmt.Println(strings.Repeat(a, 2)) // 输出:hellohello
// 替换字符串中的指定子串
fmt.Println(strings.Replace(a, "e", "E", -1)) // 输出:hEllo
// 使用指定分隔符分割字符串为切片
fmt.Println(strings.Split("a-b-c", "-")) // 输出:[a b c]
// 将字符串转换为小写
fmt.Println(strings.ToLower(a)) // 输出:hello
// 将字符串转换为大写
fmt.Println(strings.ToUpper(a)) // 输出:HELLO
// 返回字符串的长度(字节数)
fmt.Println(len(a)) // 输出:5
b := "你好"
// 返回字符串的长度(字节数)
fmt.Println(len(b)) // 输出:6
}
代码解释:
这个代码片段展示了 Go 语言中 strings
包中一些常用的字符串操作函数的用法,包括判断是否包含、计数、前缀和后缀判断、索引查找、连接、重复、替换、分割、大小写转换以及获取字符串长度。注意,在计算字符串长度时,使用的是字节数,而不是字符数。
fmt
goCopy code
package main
import "fmt"
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
// 使用 fmt.Println 输出多个值
fmt.Println(s, n) // 输出:hello 123
fmt.Println(p) // 输出:{1 2}
// 使用 fmt.Printf 进行格式化输出
fmt.Printf("s=%v\n", s) // 输出:s=hello
fmt.Printf("n=%v\n", n) // 输出:n=123
fmt.Printf("p=%v\n", p) // 输出:p={1 2}
fmt.Printf("p=%+v\n", p) // 输出:p={x:1 y:2}
fmt.Printf("p=%#v\n", p) // 输出:p=main.point{x:1, y:2}
f := 3.141592653
fmt.Println(f) // 输出:3.141592653
fmt.Printf("%.2f\n", f) // 输出:3.14
}
代码解释:
-
type point struct { ... }
:定义了名为point
的结构体类型,包含两个整数字段x
和y
。 -
使用
fmt.Println(s, n)
:使用fmt.Println
函数同时输出多个值,结果为hello 123
。 -
使用
fmt.Printf
进行格式化输出:fmt.Printf("s=%v\n", s)
:使用%v
占位符将变量的值插入字符串中,结果为s=hello
。fmt.Printf("n=%v\n", n)
:同样,使用%v
插入变量的值,结果为n=123
。fmt.Printf("p=%v\n", p)
:使用%v
插入结构体变量p
的值,结果为p={1 2}
。fmt.Printf("p=%+v\n", p)
:使用%+v
插入结构体变量p
的值,带有字段名,结果为p={x:1 y:2}
。fmt.Printf("p=%#v\n", p)
:使用%#v
插入结构体变量p
的值,带有完整的类型和字段名,结果为p=main.point{x:1, y:2}
。
-
使用
fmt.Println(f)
:输出浮点数f
的值,结果为3.141592653
。 -
使用
fmt.Printf("%.2f\n", f)
:使用%.2f
格式控制符将浮点数f
格式化为小数点后保留两位的形式,结果为3.14
。
json
goCopy code
package main
import (
"encoding/json"
"fmt"
)
type userInfo struct {
Name string
Age int `json:"age"` // 自定义 JSON 标签
Hobby []string `json:"hobbies"` // 自定义 JSON 标签
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
// 将结构体编码为 JSON 格式的字节切片
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf) // 输出:[123 34 78 97...]
fmt.Println(string(buf)) // 输出:{"Name":"wang","age":18,"hobbies":["Golang","TypeScript"]}
// 使用 json.MarshalIndent 进行格式化输出
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
// 将 JSON 格式的字节切片解码为结构体
var b userInfo
err = json.Unmarshal(buf, &b)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", b) // 输出:main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}
}
代码解释:
type userInfo struct { ... }
:定义了userInfo
结构体类型,包含Name
、Age
和Hobby
字段。使用json
标签来自定义字段在 JSON 中的名称。json.Marshal(a)
:使用json.Marshal
函数将a
结构体编码为 JSON 格式的字节切片。json.MarshalIndent(a, "", "\t")
:使用json.MarshalIndent
函数对a
结构体进行格式化编码,第二个参数是前缀,第三个参数是缩进字符串。json.Unmarshal(buf, &b)
:使用json.Unmarshal
函数将 JSON 格式的字节切片解码为结构体变量b
。
time
goCopy code
package main
import (
"fmt"
"time"
)
func main() {
// 获取当前时间
now := time.Now()
fmt.Println(now) // 输出当前时间,类似:2022-03-27 18:04:59.433297 +0800 CST m=+0.000087933
// 构造指定时间
t := time.Date(2022, 3, 27, 1, 25, 36, 0, time.UTC)
t2 := time.Date(2022, 3, 27, 2, 30, 36, 0, time.UTC)
fmt.Println(t) // 输出:2022-03-27 01:25:36 +0000 UTC
// 获取时间的年、月、日、小时、分钟
fmt.Println(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()) // 输出:2022 March 27 1 25
// 格式化时间为字符串
fmt.Println(t.Format("2006-01-02 15:04:05")) // 输出:2022-03-27 01:25:36
// 计算时间差
diff := t2.Sub(t)
fmt.Println(diff) // 输出:1h5m0s
fmt.Println(diff.Minutes(), diff.Seconds()) // 输出:65 3900
// 解析字符串为时间对象
t3, err := time.Parse("2006-01-02 15:04:05", "2022-03-27 01:25:36")
if err != nil {
panic(err)
}
fmt.Println(t3 == t) // 输出:true
// 获取当前时间的 Unix 时间戳
fmt.Println(now.Unix()) // 输出当前时间的 Unix 时间戳,类似:1648738080
}
代码解释:
time.Now()
:获取当前时间。time.Date(year, month, day, hour, minute, second, nanosecond, location)
:构造指定时间。t.Year()
,t.Month()
,t.Day()
,t.Hour()
,t.Minute()
:获取时间的年、月、日、小时、分钟。t.Format(layout)
:将时间格式化为指定的字符串。t2.Sub(t)
:计算时间差。time.Parse(layout, value)
:将字符串解析为时间对象。now.Unix()
:获取当前时间的 Unix 时间戳。
strconv
goCopy code
package main
import (
"fmt"
"strconv"
)
func main() {
// 将字符串转换为浮点数
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) // 输出:1.234
// 将字符串转换为整数
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n) // 输出:111
// 支持十六进制转换
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) // 输出:4096
// 将字符串转换为整数,简便函数 Atoi
n2, _ := strconv.Atoi("123")
fmt.Println(n2) // 输出:123
// Atoi 在无法解析时会返回 0 和错误信息
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err) // 输出:0 strconv.Atoi: parsing "AAA": invalid syntax
}
代码解释:
strconv.ParseFloat(input, bitSize)
:将字符串转换为浮点数,bitSize
表示浮点数的位数。strconv.ParseInt(input, base, bitSize)
:将字符串转换为整数,base
表示输入的字符串是何种进制(0 表示自动识别进制),bitSize
表示整数的位数。strconv.Atoi(input)
:将字符串转换为整数,这是strconv.ParseInt
的简便函数,自动识别进制。- 在
strconv.Atoi
中,无法解析时会返回 0 和错误信息。
env
goCopy code
package main
import (
"fmt"
"os"
"os/exec"
)
func main() {
// 输出命令行参数
fmt.Println(os.Args) // 输出:[/var/folders/8p/n34xxfnx38dg8bv_x8l62t_m0000gn/T/go-build3406981276/b001/exe/main a b c d]
// 获取环境变量
fmt.Println(os.Getenv("PATH")) // 输出环境变量 PATH 的值
// 设置环境变量
fmt.Println(os.Setenv("AA", "BB")) // 设置环境变量 AA 的值为 BB
// 执行外部命令并获取输出
buf, err := exec.Command("grep", "127.0.0.1", "/etc/hosts").CombinedOutput()
if err != nil {
panic(err)
}
fmt.Println(string(buf)) // 输出 grep 命令在 /etc/hosts 中查找的结果
}
代码解释:
os.Args
:获取命令行参数,包括程序名和参数列表。os.Getenv(name)
:获取环境变量的值。os.Setenv(name, value)
:设置环境变量的值。exec.Command(command, args...)
:创建一个命令对象,command
表示命令名称,args...
表示命令参数。cmd.CombinedOutput()
:执行命令并获取标准输出和标准错误输出,如果命令执行失败,则返回错误。