一.变量
1.变量的声明
//写法一
var a,b int
a,b = 1,2//平行赋值语句
//写法二
var a,b int = 1,2
//写法三
var a,b = 1,2
//写法四
a,b := 1,2
//写法五
a,b := int(1),int(2)
...
其它类型的变量均可这样写
常量的声明
//常量的声明,使用 const
const s string = "constant"//显式
const s = "constant"//隐式
const a,b = 1,2
const (
Name = "小夏"
age = 18
male = true
)
二.if else
if 8%4 == 0 { // 判断8是否可以被4整除
fmt.Println("8 is divisible by 4") // 如果可以,打印"8 is divisible by 4"
}
if 7%2 == 0 { // 判断7是否为偶数
fmt.Println("7 is even") // 如果是,打印"7 is even"
} else {
fmt.Println("7 is odd") // 如果不是,打印"7 is odd"
}
if num := 9; num < 0 { // 定义一个变量num并赋值为9,判断num是否小于0
fmt.Println(num, "is negative") // 如果是,打印变量num的值以及"is negative"
} else if num < 10 { // 如果num不小于0,判断num是否小于10
fmt.Println(num, "has 1 digit") // 如果是,打印变量num的值以及"has 1 digit"
} else {
fmt.Println(num, "has multiplle digits") // 如果不是,打印变量num的值以及"has multiplle digits"
}
三.循环
Go语言中没有 for、while、do while三种循环之分
只有一种循环,就是for循环
// 初始化 i 的值为 1
i := 1
// 无限循环,直到遇到 break 跳出循环
for {
fmt.Println("loop")
break
}
// 循环从 7 到 8,输出 j 的值
for j := 7; j < 9; j++ {
fmt.Println(j)
}
// 循环从 0 到 4,如果 n 是偶数则继续下一次循环,否则输出 n 的值
for n := 0; n < 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
}
// 循环条件是 i 小于等于 3,输出 i 的值并将 i 加 1
for i <= 3 {
fmt.Println(i)
i = i + 1
}
四.switch
与C++不同的是,不需要加break
// 初始化 a 的值为 2
a := 2
// 根据 a 的值进行分支判断
switch a {
case 1:
fmt.Println("one")
case 2,3:// 可以将多个值合并到一个分支中,用逗号分隔
fmt.Println("two or three")
default:
fmt.Println("other")
}
// 获取当前时间
t := time.Now()
// 根据时间的小时数进行分支判断
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
五.数组,切片(Slice),Map(Go语言 数组、切片、map的区别-CSDN博客)
类型比较
数组:值类型 切片:引用类型 map:引用类型
语法比较
数组的语法:var name [5]string []必须指定长度数字
var a [10]int //声明数组
切片的语法:var name []string
var b []int //声明切片
map的语法:var map变量名 map[key类型]vlaue类型 []中必须指定类型
var c map[string]int //声明map类型
初始化比较
切片和map是可以被make初始化的,数组不行,数组必须在声明时初始化。
初始化之后才能有内存地址
func main() {
a := make([]int,5,10)
b := make(map[string]int,10)
fmt.Printf("%T\n",a)
fmt.Printf("%T",b)
}
输出结果:
[]int
map[string]int
另外,new和make都是用于初始化的,它们两个区别在于new只能初始化值类型(int、string等),make只能初始化引用类型(切片、map、channel)
具体部分看CSDN的文章Go语言 数组、切片、map的区别_map和数组的区别_登云时刻的博客-CSDN博客
六.range(Go 语言范围(Range)_go range-CSDN博客)
Go 语言中 range 关键字用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素。
在数组和切片中它返回元素的索引和索引对应的值,在集合中返回 key-value 对。
for 循环的 range 格式可以对 slice、map、数组、字符串 等进行迭代循环。
格式如下:
for key, value := range oldMap {
newMap[key] = value
}
以上代码中的 key 和 value 是可以省略。
如果只想读取 key,格式如下:
for key := range oldMap
或者这样:
for key, _ := range oldMap
如果只想读取 value,格式如下:
for _, value := range oldMap
range 关键字在 go 语言中是相当常用好用的语法糖,可以用在 for 循环中迭代 array、slice、map、channel、字符串所有涉及到遍历输出的东西。
七.函数
// add 函数将两个整数相加并返回其结果。
func add(a int, b int) int {
return a + b
}
// add2 函数与 add 函数相同,但使用了简化的参数语法。
func add2(a, b int) int {
return a + b
}
// exists 函数检查给定键是否存在于给定的字符串键值对映射中。
// 如果键存在,则返回键的值和 true,否则返回 "" 和 false。
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
func main() {
// 调用 add 函数并打印结果。
res := add(1, 2)
fmt.Println(res)
// 调用 exists 函数检查键 "a" 是否存在于 map 中,并打印结果。
v, ok := exists(map[string]string{"a": "A"}, "a")
fmt.Println(v, ok)
}
八.指针
// add2 函数接受一个整数并将其加 2,但它不会改变原始参数的值。
func add2(n int) {
n += 2
}
// add2ptr 函数接受一个指向整数的指针,并将该整数加 2。
// 由于它接受的是指针,因此它可以修改原始参数的值。
func add2ptr(n *int) {
*n += 2
}
func main() {
// 创建一个整数变量 n 并初始化为 5。
n := 5
// 调用 add2 函数并打印 n 的值。
add2(n)
fmt.Println(n) // 输出:5
// 调用 add2ptr 函数并打印 n 的值。
// 由于 add2ptr 接受的是指针,它会修改原始参数的值。
add2ptr(&n)
fmt.Println(n) // 输出:7
}
九.结构体
// 定义一个名为 user 的结构体,表示用户的信息。
type user struct {
name string
password string
}
func main() {
// 创建四个 user 变量,并分别使用不同的方式初始化它们的值。
a := user{name: "wang", password: "1024"} // 使用字段名初始化。
b := user{"wang", "1024"} // 直接使用值初始化,字段顺序必须与结构体定义中的顺序一致。
c := user{name: "wang"} // 仅初始化 name 字段,password 字段将为默认值 ""。
c.password = "1024" // 然后使用赋值语句为 password 字段赋值。
var d user // 声明一个 user 变量,所有字段都将为默认值 ""。
d.name = "wang" // 然后使用赋值语句为两个字段赋值。
d.password = "1024"
// 打印这四个变量的值。
fmt.Println(a, b, c, d)
// 调用 checkPassword 函数检查密码是否正确,它接受一个 user 参数和一个密码字符串。
fmt.Println(checkPassword(a, "haha")) // 输出 false,因为密码不匹配。
// 调用 checkPassword2 函数检查密码是否正确,它接受一个指向 user 的指针和一个密码字符串。
fmt.Println(checkPassword2(&a, "haha")) // 输出 false,因为密码不匹配。
}
// checkPassword 函数检查给定用户的密码是否匹配,它接受一个 user 参数和一个密码字符串。
func checkPassword(u user, password string) bool {
return u.password == password
}
// checkPassword2 函数检查给定用户的密码是否匹配,它接受一个指向 user 的指针和一个密码字符串。
func checkPassword2(u *user, password string) bool {
return u.password == password
}
type user struct {
name string
password string
}
// checkPassword 方法检查给定用户的密码是否匹配,它接受一个 password 参数。
// 它是一个值接收器,因此不会修改 user 的值。
func (u user) checkPassword(password string) bool {
return u.password == password
}
// resetPassword 方法将给定用户的密码重置为指定的值,它接受一个 password 参数。
// 它是一个指针接收器,因此可以修改 user 的值。
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
// 创建一个 user 变量,并初始化它的值。
a := user{name: "wang", password: "1024"}
// 使用 resetPassword 方法将密码重置为新的值。
a.resetPassword("2048")
// 使用 checkPassword 方法检查密码是否正确,并输出结果。
fmt.Println(a.checkPassword("2048")) // 输出 true,因为密码已被重置为 2048。
}
十.错误的处理
type user struct {
name string
password string
}
// findUser 方法接收一个 user 切片和一个 name 字符串,它返回指向找到的用户的指针和一个错误。
// 如果找到了用户,则 err 返回 nil,否则返回错误信息。
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() {
// 查找一个存在的用户
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name) // 输出 "wang"
// 查找一个不存在的用户
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u.name) // 不会被执行,因为 u 是 nil 指针,访问它的 name 属性会导致 panic。
}
}
十一.字符串
func main() {
a := "hello"
// 判断字符串 a 中是否包含 "ll" 子串
fmt.Println(strings.Contains(a, "ll"))
// 计算字符串 a 中 "l" 字符出现的次数
fmt.Println(strings.Count(a, "l"))
// 判断字符串 a 是否以 "he" 开头
fmt.Println(strings.HasPrefix(a, "he"))
// 查找字符串 a 中 "ll" 子串的位置
fmt.Println(strings.Index(a, "ll"))
// 将字符串切片 ["he", "llo"] 按照 "-" 连接为一个字符串
fmt.Println(strings.Join([]string{"he", "llo"}, "-"))
// 将字符串 a 重复两次
fmt.Println(strings.Repeat(a, 2))
// 将字符串 a 中的 "e" 字符替换为 "E",-1 表示替换所有匹配的字符
fmt.Println(strings.Replace(a, "e", "E", -1))
// 将字符串 "a-b-c" 按照 "-" 分隔为切片 ["a", "b", "c"]
fmt.Println(strings.Split("a-b-c", "-"))
// 将字符串 a 转换为小写字母
fmt.Println(strings.ToLower(a))
// 将字符串 a 转换为大写字母
fmt.Println(strings.ToUpper(a))
// 计算字符串 a 的长度
fmt.Println(len(a))
b := "你好"
// 计算字符串 b 的长度,UTF-8 编码下一个汉字占用三个字节
fmt.Println(len(b))
}
type point struct {
x, y int
}
func main() {
s := "hello"
n := 123
p := point{1, 2}
// 使用 Println 输出字符串和整数
fmt.Println(s, n)
// 使用 Println 输出结构体
fmt.Println(p)
// 使用 Printf 输出格式化字符串
fmt.Printf("s=%v\n", s)
fmt.Printf("n=%v\n", n)
// 使用 %+v 输出带字段名的结构体
fmt.Printf("p=%+v\n", p)
// 使用 %#v 输出带类型和字段名的结构体
fmt.Printf("p=%#v\n", p)
f := 3.141592653
// 输出浮点数
fmt.Println(f)
// 使用格式化字符串输出浮点数,保留 2 位小数
fmt.Printf("%.2f\n", f)
}
十二.JSON的处理
type userInfo struct {
Name string
Age int `json:"age"` // 对 Age 字段添加了 tag,用于指定 JSON 编码和解码时对应的字段名
Hobby []string
}
func main() {
a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
// 将 struct 转换为 JSON 字节数组
buf, err := json.Marshal(a)
if err != nil {
panic(err)
}
fmt.Println(buf) // [123 34 78 97 109 ... 34 93 125]
fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}
// 将 struct 转换为格式化后的 JSON 字节数组
buf, err = json.MarshalIndent(a, "", "\t")
if err != nil {
panic(err)
}
fmt.Println(string(buf))
// {
// "Name": "wang",
// "age": 18,
// "Hobby": [
// "Golang",
// "TypeScript"
// ]
// }
// 将 JSON 字节数组转换为 struct
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"}}
}
十三.时间
func main() {
now := time.Now() // 获取当前时间
fmt.Println(now) // 打印当前时间
t := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.UTC) // 创建一个时间对象,与 now 时间只差秒以下部分
t2 := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.UTC) // 创建另一个时间对象,与 now 时间只差秒以下部分
fmt.Println(t) // 打印 t
fmt.Println(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second()) // 打印 now 的年月日时分秒
fmt.Println(t.Format("2004-06-20 13:50:02")) // 格式化输出 t
diff := t2.Sub(t) // 计算 t2 与 t 之间的时间差
fmt.Println(diff) // 打印时间差
fmt.Println(diff.Minutes(), diff.Seconds()) // 打印时间差的分钟数和秒数
t3, err := time.Parse("2004-06-20 13:50:02", "2023-05-14 15:29:04") // 解析时间字符串,得到一个时间对象
if err != nil {
panic(err)
}
fmt.Println(t3 == t) // 判断 t3 是否等于 t
fmt.Println(now.Unix()) // 获取当前时间的 Unix 时间戳
}
十四.数字解析
func main() {
//将字符串 "1.234" 转换成 float64 类型的浮点数
f, _ := strconv.ParseFloat("1.234", 64)
fmt.Println(f) //1.234
//将字符串 "111" 转换成 int64 类型的整数
n, _ := strconv.ParseInt("111", 10, 64)
fmt.Println(n) //111
//将字符串 "0x1000" 转换成 int64 类型的整数,0 表示自动判断进制
n, _ = strconv.ParseInt("0x1000", 0, 64)
fmt.Println(n) //4096
//将字符串 "123" 转换成 int 类型的整数
n2, _ := strconv.Atoi("123")
fmt.Println(n2) //123
//将字符串 "AAA" 转换成 int 类型的整数,由于 "AAA" 不是合法的整数字符串,会返回解析错误
n2, err := strconv.Atoi("AAA")
fmt.Println(n2, err)//0 strconv.Atoi: parsing "AAA": invalid syntax
}
十五.进程信息
func main() {
fmt.Println(os.Args) // 打印命令行参数
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() // 执行 grep 命令查找 /etc/hosts 中包含 "127.0.0.1" 的行
if err != nil {
panic(err)
}
fmt.Println(string(buf)) // 打印 grep 命令输出的结果
}