方法 | 介绍 |
---|---|
len(str) | 求长度 |
strings.Split | 分割 |
strings.Contains | 判断是否包含 |
strings.HasPrefix,strings.HasSuffix | 前缀/后缀判断 |
strings.Index(),strings.LastIndex() | 子串出现的位置 |
string中每个元素叫"字符",字符有两种
string底层是byte数组,string的长度就是该byte数组的长度,utf-8编码下一个汉字占3个byte,即一个汉字占3个长度.
string可以转换为[]byte或[]rune类型
string是常量,不能修改其中的字符.
byte和int客户互相转换,但byte默认是uint8所以超出255之后就会转换出错.
float和int可以互相转换,但小数点后会丢失
bool和int不能互相转换
不同长度的int或float之间可以相互转换
string可以转换为[]byte或[]rune类型,byte或rune可以转换为string
低精度向高精度转换没问题,高精度向低精度转换会丢失位数
无符号向有符号转换,最高位是符号位
第一: 长度固定
第二: 连续的内存空间
第三: 同一类型的集合
数组是块连续的内存空间,在声明的时候必须指定长度,且长度不能改变.所以数组在声明的时候就可以把内存空间分配好,并赋上默认值即完成了初始化.
var arr1 [5]int = [5]int{}
var arr2 = [5]int{}
var arr3 = [5]int{3,2}
var arr4 = [5]int{2: 15,3: 20}
var arr5 = [...]int{3,2,4,5,9}
var arr6 = [5][3]int{{1,2},{3}}
var arr7 = [...][3]int{{1},{2,3}} // 2行3列 第一个行可以...第二个列不能...
读
首元素: arr[0]
末元素: arr[len(arr)-1]
二维数组: arr[2][3]
一维数组
var arr1 = [...]int{1, 2, 4, 6, 7, 8, 9}
// 方法1:
for i, ele := range arr1 {
fmt.Printf("index=%d, element=%d\n", i, ele)
}
// 方法2:
for i :=0;i< len(arr1);i++ {
fmt.Printf("index=%d, element=%d\n", i, arr1[i])
}
二维数组
var arr2 = [...][4]int{{4,5,7},{0,2},{1,3,4,6}}
for row,array3 := range arr2 {
for col, ele := range array3 {
fmt.Printf("arr[%d][%d]=%d\n",row,col,ele)
}
求平均数
func Avg1() {
var arr1 = [...]int{33,56,78,44,78,49,98,36,87}
var count int = 0
for i:=0;i<len(arr1);i++ {
count += arr1[i]
}
fmt.Printf("平均数等于=%f",float32(count)/float32((len(arr1))))
}
cap代表capacity容量
len代表length长度
len代表目前数组里面的几个元素,cap代表给数组分配的内存空间可以容纳多少个元素
由于数组初始化之后长度不会改变,不需要给他预留内存空间,所以len(arr)==cap(arr)
数组的长度和类型都是数组类型的一部分,函数传递数组类型时这两部分都必须吻合
go语言没有按引用传参,全部是按值传参,即传递数组实际上是进行数组的拷贝,当数组的长度很大时,传参开销都很大
如果想修改函数外部数组,就把他的指针传进来.
byte和rune类型都是字符串
byte表示的是ascii码,ASCII不能直接表示中文
rune表示utf-8码(一个中文3个字节,一个英文是1个字节)
s := "hello world"
fmt.Println(len(s))
s_zh := "你好中国"
fmt.Println(len(s_zh))
结果:
11
12
s := "hello world"
s_zh := "你好中国"
s_new := s_zh + s
fmt.Println(s_new)
结果:
你好中国hello world
str := "22+11+38"
arr1 := strings.Split(str, "+")
fmt.Printf("%T:%v", arr1, arr1)
结果:
[]string:[22 11 38]
str2 := strings.Join(arr1, "-")
fmt.Printf("%T:%v", str2, str2)
结果:
string:22-11-38
单引号只能表示一个字符
a := 'a' //正确
a1 := 'aa' //错误
s := "hello 中国"
for _, val := range s {
fmt.Printf("%T:%v:%c\n", val, val, val)
}
结果:
int32:104:h
int32:101:e
int32:108:l
int32:108:l
int32:111:o
int32:32:
int32:20013:中
int32:22269:国
// 1. 数字转成字符串
num := 100
fmt.Printf("%T:%d\n", num, num)
strNum := strconv.Itoa(num)
fmt.Printf("%T:%s\n", strNum, strNum)
结果:
int:100
string:100
字符转数字时可能会有err,需要加一段if避免报错中断
// 2. 字符串转数字
intNum, err := strconv.Atoi(strNum)
if err != nil {
fmt.Print(err)
}
fmt.Printf("%T:%d", intNum, intNum)
结果:
int:100
切片和数组区别: 切片长度不固定,可以根据需求自动扩容.数组长度固定
切片包括,地址,长度,容量
数组包含两个标识:地址,长度没有容量
第一. 长度可变
第二. 连续内存空间
第三.同一类型集合
//切片
a := []string{"sh","bj","hz"}
//数组
b := [...]string{"西安","吉林","无锡"}
c := [3]int{1,2,3}
拥有相同类型的可变长度的集合
切片之间不能比较
切片的本质就是对底层数组的封装,它包含了三个信息.底层数组的 指针,切片的长度(len),切片的容量(cap)
s1内存了: 指针–>开始位置,长度 3,容量8.只是对原有数据的引用
长度就是不算当前位置,到结尾有多少个.
容量就是算当前位置,到数组末尾有多少个位置
b := [8]int{1, 2, 3, 4, 5, 6, 7, 8}
s1 := b[3:6]
fmt.Println(s1)
fmt.Printf("长度%v,容量%v\n", len(s1), cap(s1))
结果:
[4 5 6]
长度3,容量5
b := [8]int{1, 2, 3, 4, 5, 6, 7, 8}
s1 := b[0:5]
fmt.Println(s1)
fmt.Printf("长度%v,容量%v\n", len(s1), cap(s1))
结果:
[1 2 3 4 5]
长度5,容量8
两种切片方法.
b := [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
s1 := b[2:8]
fmt.Println(s1)
fmt.Printf("长度%v,容量%v\n", len(s1), cap(s1))
for i := 0; i < len(s1); i++ {
fmt.Println(s1[i])
}
for _, value := range s1 {
fmt.Println(value)
}
y := []int{1, 2}
y = append(y, 6, 7, 8)
fmt.Println(y)
fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
结果:
[1 2 6 7 8]
长度:5,容量:6
z := []int{99, 88}
y := []int{1, 2}
y = append(y, 6, 7, 8)
fmt.Println(y)
fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
// 合并z和y
y = append(y, z...)
fmt.Println(y)
fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
结果
[1 2 6 7 8]
长度:5,容量:6
[1 2 6 7 8 99 88]
长度:7,容量:12
z := []int{99, 88}
y := []int{1, 2}
y = append(y, 6, 7, 8)
fmt.Println(y)
fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
// 合并z和y
y = append(y, z...)
fmt.Println(y)
fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
// 删除切片中的第二个元素
y = append(y[:1], y[2:]...)
fmt.Println(y)
fmt.Printf("长度:%v,容量:%v\n", len(y), cap(y))
结果
[1 2 6 7 8]
长度:5,容量:6
[1 2 6 7 8 99 88]
长度:7,容量:12
[1 6 7 8 99 88]
长度:6,容量:12
userinfo := map[string]int{
"张三": 11,
"李四": 78,
}
fmt.Println(userinfo)
结果
map[张三:11 李四:78]
userinfo := map[string]int{
"张三": 11,
"李四": 78,
}
fmt.Println(userinfo)
// 判断key是否存在
val, ok := userinfo["张三"]
fmt.Println(val, ok)
val, ok = userinfo["zhangsan"]
fmt.Println(val, ok)
结果
11 true
0 false
userinfo := map[string]int{
"张三": 11,
"李四": 78,
}
fmt.Println(userinfo)
// 判断key是否存在
val, ok := userinfo["张三"]
//fmt.Println(val, ok)
//val, ok = userinfo["zhangsan"]
fmt.Println(val, ok)
if ok {
fmt.Println(val, ok)
} else {
fmt.Println("该数据不存在")
}
或者
userinfo := map[string]int{
"张三": 11,
"李四": 78,
}
// 判断key是否存在
if val, ok := userinfo["张三"]; ok {
fmt.Println(val, ok)
} else {
fmt.Println("该数据不存在")
}
fmt.Println(userinfo)
delete(userinfo, "李四")
fmt.Println(userinfo)
结果
map[张三:11 李四:78]
map[张三:11]
方法1:
// 定义map
userInfo := map[string]int{
"zhangsan": 22,
"liudehua": 52,
"lixiaolong": 68,
"luban": 250,
}
// 1. for range 遍历key
for k := range userInfo {
if val, ok := userInfo[k]; ok {
fmt.Println(k, val)
}
}
结果
zhangsan 22
liudehua 52
lixiaolong 68
luban 250
方法2:
for key1, value1 := range userInfo {
fmt.Println(key1, value1)
}
结果
zhangsan 22
liudehua 52
lixiaolong 68
luban 250
第一步,定义变量
第二步,内存中申请一块空间,用来存放变量的值
第三步,要得到变量的值,先获取到变量的内存地址
a := 100
fmt.Println(&a)
结果
0xc0000a6058 //这个就是变量a的内存地址
取出内存中的值
a := 100
fmt.Println(&a)
fmt.Printf("%d\n", &a)
b := &a
fmt.Println(*b)
结果
0xc0000a6058
824634400856
100
获取指针类型
*int是指针类型,0xc0000180c8是内存地址位置
fmt.Printf("%T:%v\n", &a, &a)
结果
*int:0xc0000180c8
通过make方法申请空间使用
//默认长度是3,默认容量是10
t := make([]int, 3, 10)
fmt.Println(t)
fmt.Println(len(t), cap(t))
结果
[0 0 0]
3 10
通过new方法申请空间
make创建的是值类型,new创建的是指针类型
t := make([]int, 3, 10)
v := new([]int)
fmt.Printf("make:%T new:%T", t, v)
结果
make:[]int new:*[]int
make和new的区别: