GO基础部分(下)


一、数组

1.数组的一些知识

1.数组:是同一种数据类型的固定长度的序列
2.数组的长度必须是常量,且长度不可修改。例: var a [10]int
3.长度是数组类型的一部分,因此 var a [5]intvar a [10]int是不同类型。
4.数组可以通过下标访问,下标从 0len-1
5.访问越界:如果访问的下标超出数组范围,则触发访问越界,会 panic
6.数组是值类型,因此赋值和传参会复制整个数组。
7.支持"==""!="操作符,因为内存总是被初始化过

2.一维数组和多维数组

一维数组:
    a := [3]int{1, 2}           // 未初始化元素值为 0。
    b := [...]int{1, 2, 3, 4}   // 通过初始化值确定数组长度。
    c := [5]int{2: 100, 4: 200} // 使用索引号初始化元素。
多维数组(这里以二维数组为例):
    a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
    b := [...][2]int{{1, 1}, {2, 2}, {3, 3}}

3.遍历

一维数组遍历:
	for k,v :=range a{
	 	fmt.Println(k, v)
	}
多维数组遍历:
    for k1, v1 := range a {
        for k2, v2 := range v1 {
            fmt.Println( k1, k2, v2)
        }
    }

二、切片(slice)

1.切片的一些知识

slice 并不是数组或数组指针。它通过内部指针和相关属性引用数组片段

    1. 切片:切片是数组的一个引用,因此切片是引用类型。但自身是结构体,值拷贝传递。
    2. 切片的长度可以改变,因此,切片是一个可变的数组。
    3. 切片遍历方式和数组一样,可以用len()求长度。表示可用元素数量,读写操作不能超过该限制。 
    4. cap可以求出slice最大扩张容量,不能超出数组限制。0 <= len(slice) <= len(array),其中array是slice引用的数组。
    5. 切片的定义:var 变量名 []类型,比如 var str []string  var arr []int6. 如果 slice == nil,那么 lencap 结果都等于 0

2.创建切片

//  声明切片
var s1 []int
//  :=
s2 :=[]int{}
//   make(Type,len,cap)
//使用 make 动态创建slice,避免了数组必须用常量做长度的麻烦。
s3 := make([]int,0)
//   初始化赋值
s4 := []int{1,2,3,4,5}
//   通过数组切片
a :=[5]int{1,2,3,4,5]
//	 左包右不包
s5 :=a[1:4]  //2,3,4

3.切片的一些基本操作

s[n]				切片 s 中索引为 n 的项
s[:]				从切片 s 中索引 0 到 索引len(s)-1 处所获得的切片
s[m:n]				从切片 s 中索引 m 到索引 n 处所获得的切片
len(s)				切片的长度,总是<=cap(s)
cap(s)				切片的容量,总是>=len(s)

4.用append内置函数操作切片(切片追加)

append :向 slice 尾部添加数据,返回新的 slice 对象。

package main

import (
    "fmt"
)

func main() {
    var a = []int{1, 2, 3}
    fmt.Printf("slice a : %v\n", a)
    var b = []int{4, 5, 6}
    fmt.Printf("slice b : %v\n", b)
    c := append(a, b...)
    fmt.Printf("slice c : %v\n", c)
    d := append(c, 7)
    fmt.Printf("slice d : %v\n", d)
    e := append(d, 8, 9, 10)
    fmt.Printf("slice e : %v\n", e)
}

输出结果:

    slice a : [1 2 3]
    slice b : [4 5 6]
    slice c : [1 2 3 4 5 6]
    slice d : [1 2 3 4 5 6 7]
    slice e : [1 2 3 4 5 6 7 8 9 10]

5.扩容策略

可以通过查看$GOROOT/src/runtime/slice.go源码,其中扩容相关代码如下:

GO 1.18版本:

	newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		const threshold = 256
		if old.cap < threshold {
			newcap = doublecap
		} else {
			//检查 0 < newcap 以检测溢出并防止无限循环
			for 0 < newcap && newcap < cap {
				//从小切片增长 2 倍过渡到大切片增长 1.25 倍
				// 平缓newcap增加
				newcap += (newcap + 3*threshold) / 4
			}
			// 如果newcap计算溢出,则设置为cap
			if newcap <= 0 {
				newcap = cap
			}
		}
	}

6.对切片的操作

1.复制Copy()
Copy():

Go语言内建的copy()函数可以迅速地将一个切片的数据复制到另外一个切片空间中
copy()函数的使用格式如
copy(destSlice, srcSlice []T)  //srcSlice: 数据来源切片   destSlice: 目标切片
func main() {
	// copy()复制切片
	a := []int{1, 2, 3, 4, 5}
	c := make([]int, 5, 5)
	copy(c, a)     //使用copy()函数将切片a中的元素复制到切片c
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1 2 3 4 5]
	c[0] = 1000
	fmt.Println(a) //[1 2 3 4 5]
	fmt.Println(c) //[1000 2 3 4 5]
}
2.删除元素

Go语言中并没有删除切片元素的专用方法,我们可以使用切片本身的特性来删除元素。 代码如下:

func main() {
	// 从切片中删除元素
	a := []int{30, 31, 32, 33, 34, 35, 36, 37}
	// 要删除索引为2的元素
	a = append(a[:2], a[3:]...)
	fmt.Println(a) //[30 31 33 34 35 36 37]
}

7.切片的本质

切片的本质就是对底层数组的封装,它包含了三个信息:底层数组的指针、切片的长度(len)和切片的容量(cap)。举个例子,现在有一个数组a := [8]int{0, 1, 2, 3, 4, 5, 6, 7},切片s1 := a[:5],相应示意图如下。
在这里插入图片描述

三、指针

Go语言中的函数传参都是值拷贝,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量。传递数据使用指针,而无须拷贝数据。类型指针不能进行偏移和运算。Go语言中的指针操作非常简单,只需要记住两个符号:&(取地址)和*(根据地址取值)。

四、Map

map是一种无序的基于key-value的数据结构,Go语言中的map是引用类型,必须初始化才能使用。

1.Map的定义

    map[KeyType]ValueType
    
    KeyType:表示键的类型。

    ValueType:表示键对应的值的类型。

2.Map的基本使用

m1:= make(map[string]int, 8)
    m1["张三"] = 90
    m1["小明"] = 100
或者
m2 := map[string]string{
    "username": "GOgo",
    "password": "123456",
  }

3.判断键值是否存在(ok)

    m1:= make(map[string]int)
    m1["张三"] = 90
    m1["小明"] = 100
    if v,ok:=m1["张三"];ok{
    	fmt.Println(v) //90
    }

4.Map遍历

注意: 遍历map时的元素顺序与添加键值对的顺序无关。

for k, v := range m1{
        fmt.Println(k, v)
    }

5.delete删除键值对

delete(m1, "小明")

总结

本篇文章到这里就要结束了,由于结构体所涉及的知识挺多,所以我决定单独为结构体写一篇文章。
敬请期待😊。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小阿GO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值