运算符
算数运算符
+-*/
逻辑运算符
&& || !
位运算符
<< >> ^ & |
赋值运算符
= += -=
数组
var ages [30] int
var name [30]string
数组包含元素的类型和元素的个数。元素的个数(数组的长度)属于数组类型的一部分
数组是值类型
var age [30]int //声明了一个变量age 它是[30]int类型
age = [30]int{1, 2, 3, 4}
fmt.Println(age)
var age2 = [...]int{1, 2, 3, 4}
fmt.Println(age2)
var age3 = [...]int{1: 100, 9: 200}
fmt.Println(age3)
//二维数组
var a1 [3][2]int //[[0 0] [0 0] [0 0]]
a1 = [3][2]int{
{1, 2},
{3, 4},
{5, 6},
}
var a2 [3][2]int
a2 = [...][2]int{
{1, 2},
{3, 4},
{5, 6},
}
fmt.Println(a1)
fmt.Println(a2)
指针
只需要记住俩个符号 & *
//Go语言里的指针只能读不能修改,不能修改指针变量指向的地址
name := "沙河"
addrP := &name
fmt.Println(addrP) //内存地址 0xc000038230
addrV := *addrP //根据内存地址找值
fmt.Println(addrV) //沙河
切片
切片的定义
var s1 []int //没有分配内存
fmt.Println(s1 == nil) //true
//初始化
s1 = []int{1, 2, 3}
//make初始化
s2 := make([]bool, 2, 4)
fmt.Println(s2) //[false false]
fmt.Println(s1)
s3 := make([]int, 0, 4)
fmt.Println(s3 == nil) //false 因为已经分配了内存
切片的本质就是对底层数组的封装,它包含了3个信息:底层数组的指针、切片的长度和切片的容量。
切片不能直接比较
切片不存值,它就像一个框,去底层数组框值
切片的扩容策略:
1.如果申请的容量大于原来的2倍,那就直接扩容至申请的容量
2.原来的容量小于1024,那么就直接2倍
3.如果大于1024 ,就按照1.25倍去扩容
4.具体存储的值类型不同,扩容策略也有一定的不同
append
var s1 []int
s1 = append(s1, 1) //append自动扩容和初始化
fmt.Println(s1)
copy
s1 := []int{1, 2, 3}
s2 := s1
var s3 = make([]int, 3, 3)
copy(s3, s1)
s2[1] = 100
fmt.Println(s1) //[1 100 3]
fmt.Println(s2) //[1 100 3]
fmt.Println(s3) //[1 2 3]
map
//判断字符串中汉字的数量
//难点是判断一个字符是汉字
s1 := "hello哈哈"
var count int
for _, c := range s1 {
if unicode.Is(unicode.Han, c) {
count++
}
}
fmt.Println(count)
//判断字符串出现的次数
s2 := "how do you do"
s3 := strings.Split(s2, " ")
m1 := make(map[string]int, 10)
for _, w := range s3 {
fmt.Println(w)
if _, ok := m1[w]; !ok {
m1[w] = 1
} else {
m1[w]++
}
}
for key, value := range m1 {
println(key, value)
}
//map
var m1 map[string]int
fmt.Println(m1 == nil) //true
m1 = make(map[string]int, 10)
m1["哈哈"] = 1
fmt.Println(m1)
fmt.Println(m1["呵呵"]) //如果key不存在,返回的是对应类型的0值
//如果返回的值是布尔型,我们通常用ok来接收
score, ok := m1["呵呵"]
if !ok {
fmt.Println("没有")
} else {
fmt.Println("有", score)
}
delete(m1, "呵呵") //如果删除的key不存在,就什么都不干