一、数组
1.数组定义
一:var a [10]int=[10]int{1,2,3,4,5,6}
二:
var arr[10] int
fori,_:=rangearr{
fmt.Scan(&arr[i])
}
2.数组的自动推导类型
names := [5]int{1,2,3,4,5}
for_,data:=range names{
fmt.Println(data)
}
3.
2.数组作为函数参数
func main(){
//var a [5]int=[5]int{10,20,30,40,50}
a:=[...]int{10,20,30,40,50}
Modify(a)
fmt.Println(a[0])
}
func Modify(a [5]int){
a[0]=666
}
数组作为函数参数时必须给定数组个数,否则会因为数组越界运行时错误
数组作为函数参数时是按值传递的
3.数组作为函数返回值
import(
"math/rand"
"time"
"fmt"
)
func main(){
arry:=Teat()
fmt.Println(arry)
}
func Teat()[3]int{
vararr[3]int
rand.Seed(time.Now().Unix())
for i:=0;i<3;i++{
arr[i]=rand.Intn(100)
}
return arr
}
同数组作为参数一样,数组作为返回值时,需要给定数组界限
二、二维数组
func main(){
var nArry[3][4]int
//fmt.Println(len(nArry[0]))
for i:=0;i<len(nArry);i++{
for j:=0;j<len(nArry[i]);j++{
fmt.Scan(&nArry[i][j])
}
}
fmt.Println(nArry)
}
结果:
1 2 3 4 5 6 7 8 9 10 11 12
[[1 2 3 4] [5 6 7 8] [9 10 11 12]]
nArry为外层数组其中的数据类型为一个一维数组
nArry[0]即二维数组中的一个元素,即一个一维数组
三、切片
不是指向数组的指针,是一种新定义的数据结构。 包含 指向数组地址的成员、长度、容量。 runtime/slice.go
type slice struct {
*Pointer
len
cap
}
切片定义方式:
第一种:
nSlice:=[]int{1,2,3,4,5}
nSlice=append(nSlice,6,7,8)
fmt.Println(nSlice)
第二种:
var s1 []float64
s1=[]float64{1,2.3}
fmt.Println(s1)
第三种:采用make函数(make(类型,长度,容量))
s2:=make([]int,5,10)
fori:=0;i<len(s2);i++{
s2[i]=i
}
fmt.Println(s2)
fmt.Println(len(nSlice))
fmt.Println(cap(nSlice))
容量一般是从slice的开始位置到底层数据的结尾位置,容量是固定的
关于切片的一些理解:
数组是拥有固定长度的,对于切片来说类似于一个可变长数组。
想象一下插入750000条数据到数组中去,而这个数组的长度从10开始,需要进行18次的分配,最后结束的数组长度为560720 。所以最好给数组选择一个合适的大小,但是事实上你只能对大小有一个粗略的估计,所以最好选择比预期大小稍大一点的空间,而大小则为切片的实际大小。
由于append算法的帮助我们可以完成动态数组。
关于append算法:
if 数组长度 == 数组容量{
//开辟一个数组容量为原来两倍的新数组
make([]int,原始数组长度+1,数组容量*2)
//把原始数组中的值全部拷贝到新的数组中去
}
//把新值插入到数组中去
//返回新数组
举例说明:
x:=[]int{1,2,3,4}
fmt.Println(len(x))//原始数组长度
fmt.Println(cap(x))//原始数组容量
x=append(x,5)
fmt.Println(len(x))//新数组长度
fmt.Println(cap(x))//新数组容量
结果:
4
4
5
8
关于append算法的具体实现:
unc insert(original []int, position int, value int) []int { l := len(original) target := original if cap(original) == l { target = make([]int, l+1, l+10) copy(target, original[:position]) } else { target = append(target, -1) } copy(target[position+1:], original[position:]) target[position] = value return target }
来自 <https://www.openmymind.net/Controlling-Array-Growth-In-Golang/>
如果容量超过1024字节则,扩大为上一容量的1.25倍
切片的截取:
和大部分切片的原理类似都是左闭右开
切片作为函数参数:
func GetRandom(nArry[]int){
var num int
FLAG:
rand.Seed(time.Now().UnixNano())
for{
num=rand.Intn(10000)
if 999<num&&10000>num{
nArry[0]=num/1000
nArry[1]=num/100%10
nArry[2]=num/10%10
nArry[3]=num%10
for i:=0;i<len(nArry)-1;i++{
for j:=i;j<len(nArry)-1;j++{
if nArry[i]==nArry[j+1]{
goto FLAG
}
}
}
break
}
}
}
字符串可以和字符类型相互转换
func main(){
//字符切片和字符串类型 可以进行转换
////字符串
//var str string="hello"
////字符切片
var ch []byte
////类型转换
//ch=[]byte(str)
//var ch[]byte=[]byte{'h','e','l','l','o'}
ch=[]byte("hello")
//for i:=0;i<len(ch) ;i++ {
// fmt.Printf("%s",ch[i])
//}
fmt.Printf("%s",ch)
}
四、字符串
(一)字符串处理函数
1.func Contains(s string, substr string)bool
检测字符串是否包含substr,返回bool值
2.func Join(a[] string, sep string)string
通过sep把字符串连接起来
3.func Index(s string, sep string)int
在字符串s中查找sep所在的位置,找不到返回-1
4.func Repeat(s string, count int)string
重复s字符串count次,最后返回重复的数字
5.func Replace(s string,old string, new string, n int)string
在s字符串中,把old字符串替换为new字符串,n表示替换的次数,小于0表示全部替换
6.func Split(s string, sep string)[]string
把s字符串按照sep分割,返回slice
7.func Trim(s string,cutset string)string
在s字符串中的头部和尾部取出cutset指定的字符串
8.func Fields(s string)[]string
去除s字符串得空格符,并且按照空格分割返回slice
(二)字符串转换
1.Format数据类型 其它数据转化为字符串
2.Parse数据类型 字符串转化为其它数据
3.append数据类型 将其它类型转化为字符串
五、map散列表
1.map的定义
map[键数据类型]数值数据类型
(1)map的第一种定义方式
(2)利用make
因为byte类型时根据ASCII码形式存储的,所以打印出的键值为各字符所对应的ASCII码值
2.map是一种链式结构,并不按照顺序存储
3.map作为函数参数时是按址传递
4.map添加值,map的长度是自动增加的
5.map当中的键值是唯一的
6.可以通过delete(map,key)删除元素
7.map当中的值为可以为符合数据类型
例如:var m map[string][] int
六、结构体
1.结构体定义
type 结构体名 struct{
}
通过.的操作符可以访问到结构体中的数据
2.结构体数组
结构体切片
3.结构体作为函数参数
4.结构体作为函数参数其传递方式按照所定义的类型决定,比如结构体变量结构体数组为按值传递, 结构体切片以及结构体字典为按址传递
七、指针
指针 啥是指针
指针就是用来指向变量地址的变量
指针的定义
var a int var p *int = &a
var p *int p是一个空指针,不能赋值,不能调用。指针的默认值为nil,地址为0x0
野指针指向一段垃圾内存的指针,var p *int = 0xfff00,不能被使用
指针作为函数参数
按址传递
数组指针
指向数组的指针
var p *[10]int
解引用指针值为数组的地址,可以通过指针下标p[下标]直接访问数组内容
指针数组
其值为指针的数组
var p [20]*int
切片指针
指向切片的指针
var p *[]int
解引用指针值为切片地址,不能直接通过指针下标p[下标]访问切片内容,需要通过(*p)[下标]访问切片内容。
在使用append的时候,如果切片容量不够,开辟出新的内存空间,可能造成实参和形参指向的内存地址不同,栈消亡,形参不能改变实参
指针切片
其值为指针的切片
var p []*int
结构体指针
指向结构体的指针
var p *student
new
int *p = new(int)
int *p = new([10]int)
int *p = new([]int)
int *p = new(student)
啥是指针
指针就是用来指向变量地址的变量
指针的定义
var a int var p *int = &a
var p *int p是一个空指针,不能赋值,不能调用。指针的默认值为nil,地址为0x0
野指针指向一段垃圾内存的指针,var p *int = 0xfff00,不能被使用
指针作为函数参数
按址传递
数组指针
指向数组的指针
var p *[10]int
解引用指针值为数组的地址,可以通过指针下标p[下标]直接访问数组内容
指针数组
其值为指针的数组
var p [20]*int
切片指针
指向切片的指针
var p *[]int
解引用指针值为切片地址,不能直接通过指针下标p[下标]访问切片内容,需要通过(*p)[下标]访问切片内容。
在使用append的时候,如果切片容量不够,开辟出新的内存空间,可能造成实参和形参指向的内存地址不同,栈消亡,形参不能改变实参
指针切片
其值为指针的切片
var p []*int
结构体指针
指向结构体的指针
var p *student
new
int *p = new(int)
int *p = new([10]int)
int *p = new([]int)
int *p = new(student)