读书笔记之Go数据类型

只记一:
声明类型+初始化:var num2 float32 = 0.32
永远都是变量名在前 数据类型在后

1. 基本类型声明有默认值:

在这里插入图片描述

2. 结构体声明不会为nil
在这里插入图片描述

3. 四大引用类型可为nil 【而make函数专门实例化引用数据类型】
在这里插入图片描述

4. 指针类型可为nil 【而new函数专门实例化指针类型】
在这里插入图片描述

只记二:
切片、map、channel的变量名直面的是变量值的地址集合(下图中第二行结构),通过地址集合操作变量值(通过地址的操作过程被Go封装了),所以对变量的传递是对变量地址集合的拷贝!
在这里插入图片描述

注:如果函数更改了变量对应的地址集合中数据,则必须return新的地址集合!
如:函数真的在数据后添加了一个元素2,但它肯定有修改地址集合中的 size ,所以我们需要把新的地址集合返回让其刷新!

func addSlice(s []int) []int {
	s = append(s, 2)
	return s
}

数据类型转换

数据类型转换为:T(表达式)
比如:chars := []rune(str) 字符串转换为字节切片


基本数据类型

布尔型

bool :true /false 不能参与基本数据类型的运算和转换

整型(%b %o %d %x

整型是按字节数分的:int8 int16 int32 int64
对应的无符号整型:uint8 uint16 uint32 uint64

实际int uint是不存在的,int uint 会根据不同平台分别对应不同整型(32 / 64 位)

注:整型 := 默认推导为 ===> int

浮点型(%f %.2f

float32 float64

注:浮点型 := 根据系统位数推导为 ===> float32float64

字符串(%s

string

  1. 双引号
  2. 反引号可以原样输出
  3. 采用UTF-8编码(可以通过rune类型对每个utf-8字符访问)

字符(%c

byte一个字节,底层是 uint8;(只支持ASCLL编码)
rune四个字节,底层是 int32。(支持UTF-8编码 注:UTF-8兼容ASCLL,UTF-8中汉字一般需要3个及以上个字节)

注:字符型 := 默认推导为 ===> int32(rune)

数组

数组是存储相同类型数据的固定连续区域。

数组声明必须确定数组大小

和var声明变量类型类似:声明大小 || 初始化

普通声明

var 变量名 [数组大小]T

初始化声明

变量名 接受 [...]T{1,2,3}(编译器可以推到出数组大小)

遍历数组

fori:(回想string类型也可以直接用下标是按byte取的!)

	for i := 0; i < len(a); i++ {
		fmt.Println(a[i])
	}

forr:(而string遍历用forr是按rune取的!)

	for 下标, c := range a {
		fmt.Println(c)
	}


派生类型

切片 (slice) :类似Java中ArrayList用法!不适合大量查找、删除操作!

动态地分配大小的连续内存空间
在这里插入图片描述

切片的生成

从连续内存中生成切片!

一、从数组

数组名[起始位置 : 结束位置] (左闭右开)【起始位置缺省则表示从头,结束位置缺省则表示到结尾】

var a = [...]int{1,2,3} //数组
fmt.Printf("%T",a) //[3]int

s := a[1:2] // 切片
fmt.Printf("s=%v s类型:%T",s,s) //s=[2] s类型:[]int

重置切片:a[0:0]

二、声明切片
普通声明

var 切片名 []T (不会分配数据内存,是nil

初始化声明
  1. 变量名 接受 []T{1,2}[]中没有任何值的数组声明就是切片声明)
  2. 变量名 接受 make([]T,size,cap)最最常用!!!
    size:初始化定义的变量个数
    cap:预分配的元素数量,这个值设定后不影响size(该扩容还是得扩容),只是能提前分配空间,降低多次分配空间造成的性能问题
ss := make([]int,2,3) 或 ss := make([]int,2)【此时size == cap】
ss = append(ss, 1,2,3,4,5,6,7,8)
fmt.Printf("ss类型:%T ss=%v",ss,ss) /ss类型:[]int ss=[0 0 1 2 3 4 5 6 7 8] 该扩容还是会扩容

在这里插入图片描述

append()函数为切片添加元素

	s1 := make([]int,2,4)
	s1 = append(s1,1,2)
	
	s2 := make([]int,0,4)
	s2 = append(s2, s1...) /将s1全部追加给说s2
	s2 = append(s2, s1[0:2]...) /注意s1[0:2]仍然是个切片

扩容: 当超过cap 时会进行二倍扩容,如果没有初始则1、2、4、8、16……
注:就是二倍扩容,与2得整数幂没关系

copy()函数拷贝切片数据

因为切片变量传递拷贝的是地址集合,当想要拷贝数据时,就需要copy()函数!

  1. 最多copy到dst切片的size,不会跨越size!
  2. 并且默认从头覆盖dst中数据!
	src := []int{1,2,3,4}
	dst := make([]int,2,4)
	
	copy(dst,src)
	fmt.Println(dst) /[1 2]
	src := []int{1,2,3,4}
	dst := make([]int,2,4)

	copy(dst[1:],src)
	fmt.Println(dst) /[0 1]

怎样删除切片中一个数据呢?

没有专门的删除函数:

	src := []int{1,2,3,4}
	// 删除第三个元素
	src = append(src[0:2],src[3:]... )
	fmt.Println(src)  /[1 2 4]

遍历切片

因为切片和数组一样都可以用下标访问元素,所以和数组一样遍历:fori 或 forr

排序:sort只能对切片排序

src := []int{2,4,1,5}
sort.Ints(src)

将数组转换成切片即可:

sort.Ints(a[:])
  • TIPS: 数组和切片的区别
数组切片
定义固定的连续内存数据动态的连续内存数据
声明一定要声明自己的大小: [3][...]没有固定大小:[]
类型%T[3]int[]int
变量名面向数据值数据的地址
nil?面对的数据至少有默认值,nil 无关!面对的地址可能没有,可能为nil !
var 切片名 []T 方式声明切片并不会给分配内存空间!
len(s)返回数组的容量大小返回切片中有效数值个数size

映射 (map):类似Java中HashMap!适合大量的查找工作!

map的声明:map[keyType]valueType)

普通声明

var 变量名 map[keyType]valueType(不会分配数据内存,是nil

初始化声明
  1. 变量名 接受 map[keyType]valueType{k1:v1,k2:v2}
  2. 变量名 接受 make(map[keyType]valueType)

添加与获取元素

不存在会返回默认值:

	m := make(map[string]int)

	m["id"] = 2001
	fmt.Println(m["id"])  /2001
	fmt.Println(m["name"])  /0

但其实获取元素时会将是否存在作为第二个元素返回:

	v,ok := m["name"]
	if ok {
		fmt.Println(v)
	}else {
		fmt.Println("不存在")
	}

删除元素

delete(map,键)

遍历map

因为map是没有下标的,所以只能是 forr:(当然,散列表坑定是无序输出)

	mm := map[string]int{"id":1,"name":2001,"age":520}
	
	for k, v := range mm {
		fmt.Println(k,v)
	}

sync.Map :并发安全的map

sync.Map声明都会初始化(结构体与nil无关)

var map名 sync.Map 或 变量名 接受 sync.Map{各种参数(可以不写)}

操作函数

声明:

	var m sync.Map

添加元素:m.Store(k,v)

	m.Store(1,1111)

查找元素:m.Load(k)

	v,ok := m.Load(1)
	if ok {
		fmt.Println(v)
	}else {
		fmt.Println("不存在")
	}

删除元素:m.Delete(k)

m.Delete(1)

遍历

注意:sync.Map对象可以存储任何混合存储各种类型的 kye、value

	var mm sync.Map
	fmt.Println(mm)
	mm.Store(1,1111)
	mm.Store(2.1,2222)
	mm.Store("3",3333)
	mm.Range(func(k, v interface{}) bool {
		fmt.Println("iterate:",k,v)
		return true
	})

列表(list):类似Java中的LinkedList!可以快速增删的非连续数据!

Go将列表使用container/list包来实现内部的实现原理是双链表。列表能够高效地进行任意位置的元素插入和删除操作。

声明都会初始化(结构体与nil无关)

l := list.New()var ll list.List
都会初始化,且两种方法的初始化效果都是一致的。

PushXxx插入元素:任意类型元素

	var ll list.List

	ll.PushFront("first")
	ll.PushBack(0)

在这里插入图片描述

Remove删除目标元素

列表的插入函数的返回值会提供一个*list.Element结构,这个结构记录着列表元素的值及和其他节点之间的关系等信息。从列表中删除元素时,需要用到这个结构进行快速删除。

PushXxx 返回 *list.Element结构

在这里插入图片描述

注:只能通过得到 *list.Element结构 而操作列表中的数据!

fori+l.Front()遍历

l.Front() 返回 *list.Element结构

	var ll list.List
	ll.PushBack(0)
	ll.PushBack(1)

	for i := ll.Front(); i != nil; i = i.Next() {
		fmt.Println(i.Value)
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值