【Go语言】
type关键字的用法
- 定义结构体
- 定义接口
- 定义类型别名
- 类型定义
- 类型判断
别名实际上是为了更好地理解代码/
这里要分点进行记录 使用传值的例子,当两个类型不一样需要进行类型转换
type Myint int // 自定义类型,基于已有的类型自定义一个类型type Myint = int
// 在编译的时候,类型别名会被直接替换为int
上面两种方式定义的int是不同的,因为使用等于号是类型别名,不使用等于号的是重新定义了一个类型。
type Myint int
如果我们即想使用int类型,又想让这种类型的变量有自己的方法,我们可以使用type自定义一种类型,这其实也算是一种结构体,我们可以为这个结构体创建一个方法,我们就可以进行调用这个方法。
type Myint=int
这个语句就是单独地给int变量起一个别名,其他用法和int一模一样。
结构体的定义和初始化
在go语言中没有面向对象的概念,但是可以使用面向对象的思想
type Person struct {name stringage intaddress stringheight float32
}// 在进行初始化的时候,我们有两种方式:
p1 := Peason{"xiaomin", 14, "佳", 1.8}p2 := Person{name:"xiaomin",age:14,
}
匿名结构体 匿名函数
只能使用一次。
address := struct {province stringcity stringaddress string
}{"北京市","通州区","xxx",
}
结构体嵌套
有两种嵌套方式
type Person struct {name stringage int
}type student struct {p Personscore int
}type student struct {Personscore int
}
匿名定义中有一些问题,如果匿名结构体中有name,但是在外边的结构体中也有name,那么我们会发现外部的结构体的name的优先级大于匿名结构体中的优先级。
结构体定义方法
接收器有两种形态,一种是值传递,一种是指针传递,当我们需要进行修改结构体中的数值或者传递的结构体的容量很大时,我们需要进行指针传递。
如果接收器是指针类型,但是我们是值类型,我们可以进行调用函数的,同理,另一种情况也是可以的。
指针:
go语言中限制了指针的运算,在C语言中,我们可以使用指针进行加减运算,
指针的初始化
指针是需要进行初始化的
在初始化的时候,有两个关键字:make ,new
map channel slice 初始化推荐使用make方法
指针初始化推荐使用new函数,指针需要进行初始化,否则会出现nil pointer
map必须初始化,否则会出现panic
nil在go中的细节
不同类型的数据的零值不一样,
bool false
numbers 0
string ""
pointer nil
slice nil
map nil
channel interface function nil
struct 的默认值不是nil,默认值是具体字段的默认值
slice的底层介绍???????等会看一看
map也分为两种 nil map 和 empty map 在大部分场景下,nil map 和 empty map一样,但是当我们给nil map 进行赋值的时候,会进行panic
接口
什么是鸭子类型?
方法。动词,具备某些方法,go语言中强调的是动作
鸭子类型强调的是外部行为,而不是内部的结构
如何定义一个接口
type Duck interface{// 方法的申请Gaga()Walk()Swiming()
}type pskDuck struct {legs int
}func (pd *pskDuck) Gaga() {fmt.Println("this is walking...")
}func main() {var d Duck = &pskDuck{}d.Gaga()
}
多接口的实现 不是很懂
如果有两个接口中的函数出现重复,说明我们可以将函数进行复用,我们可以实现接口进行解耦。
type MyWriter interface{Write(string) error
}type MyCloser interface{Close() error
}type WriteClose struct {MyWriter // interface 也是一种类型
}func (wc *WriteClose) Writer(s string) error {fmt.Println("this is writer)return nil
}func (wc *WriteClose) Close() error {fmt.Println("this is closer")return nil
}
在go语言中,多接口的实现是通过组合接口来实现的,go不支持多重继承,但是可以让一个类型实现多个接口,具体来说,只要一个类型实现了某些方法,他就自动实现了相应的接口。通过这种方式,go语言允许一个类型轻松实现多个接口,促进了灵活的设计和代码复用。
通过interface解决动态类型传参
我们在实现一些
使用断言转换类型
但是还是没有解决问题
使用switch语句,断言处理分支语句可以用到
a.(type) 可以判断是什么类型
但是更通用的写法是泛型。
string.Split
接口嵌套
接口遇到了slice的常见错误
单元测试
Go的并发编程
go的并发编程初体验
在php,java,python等语言中,都是有多线程编程,多进程编程,多线程和多进程存在的问题主要是耗费内存。在进行进程切换和线程切换的时候,CPU会消耗一些资源。因此在go语言中,我们推出了协程(用户级线程,绿程,轻量级线程)。
在协程中,内存占用小(2k),切换快,在go语言的协程中,go余元诞生之后就只有协程可以使用——goroutine,非常方便。我们可以在程序中使用协程创建出10万以上的协程,但是线程在程序中只能创建出100多个。下面,我们来看一看协程的代码:
func asyncPrint() {fmt.Println("加油旭杏")
}// 主协程
func main() {go asyncPrint()
}
上述代码是单个协程的调用,如果我们想使用多协程进行调用,我们可以使用循环来创建出多个协程。在创建协程的时候,我们有两种方式可以进行创建:一种是直接调用函数,一种是匿名函数。代码如下:
func Print() {fmt.Println("加油旭杏")
}// 匿名结构体
func main() {go func() {for {fmt.Println("加油旭杏")}}time.Sleep(10 * time.Second)
}
这里为了使程序不退出,我们在主协程中添加了睡眠时间,但是这种方式是非常挫的,在下面我们将会学习另一种等待协程的方法。
有一个问题:在C++中,如果有多个线程去执行一个加法运算,再执行一个减法运算会出现错误的,我们需要使用锁来进行让加减操作变成原子操作。如果操作简单,我们也可以使用原子变量来进行操作。
我们来看一看下面的代码:
for i := 0; i < 100; i++ {go func() {fmt.Println(i)}()
}
第一个原因是我们使用匿名函数,也就是闭包,只能使用一次,第二个原因是我们使用了for循环,在for循环中,每一个变量会被重新使用,所以我们在调用加操作之前的变量和调用加操作之后的变量不是同一个变量,因为这个不是原子操作,也会CPU的调度有关。
go的gmp调度原理
这个gmp调度是分层的,我们先来看一看两层结构:一个是协程,一个是线程;在Go语言中,我们会将协程放入到线程去执行,
一张图 g gorounte m p
我们在协程调度的时候,我们需要将
通过waitgroup来等待协程
子gorounte如何通知到主的gorount自己结束了,主的gorounte如何知道子的gorounte已经结束了??
之前我们使用的例子是通过设置时间长度,但是我们不知道具体需要多少时间,所以这个代码是比较挫的,现在我们来认识一下WaitGroup。我们可以通过WaitGroup来将协程加入,如果我们事先知道协程的总数,可以直接在循环之前进行添加;如果我们不知道协程的总数,我们可以在循环的时候进行添加,每循环一次就添加一次,在添加之后我们需要将其进行done,类似于锁的机制一样,否则会造成死锁。因此,我们需要知道WaitGroup的add和done是需要配套使用的。最后我们需要进行wait方式进行等待。代码如下:
var wg sync.WaitGroup// 我们需要监控多少个gotountine执行结束
wg.Add(100)
for i := 0; i < 100; i++ {go func(i int) {fmt.Println(i)wg.Done(); // Done和Add要成对出现}()
}// 等待
wg.Wait()
waitgroup主要用于gorountine的执行等待,add方法主要和done方法配套,最后要使用Wait方法进行等待,否则会出现死锁。
通过mutex和atomic完成全局变量的原子操作
当我们需要进行共享资源的访问时,我们需要进行锁来对于资源竞争的保证。下面,我们来看一看代码:
func add() {defer wg.Done()for i := 0; i < 10000; i++ {lock.Lock()total += 1 // 这里会有竞争lock.Unlock()}
}func sub() {defer wg.Done()for i := 0; i < 10000; i++ {lock.Lock()total -= 1 // 这里会有竞争lock.Unlock()}
}
当我们单独执行add函数或者单独执行sub函数,结果都是正确,但是当我们两个一起执行时,结果是错的,在Linux中,我们也出现了这种情况,因为a += 1不是原子操作,当CPU进行执行这段代码时,有可能中途退出,我们需要将这段代码进行保护起来,不要让他单独执行。在go语言中的锁是一个结构体,锁可以进行复制,但是复制过后锁就失去了自身的效果。下面是将加减操作改为原子操作,代码如下:
func add() {defer wg.Done()for i := 0; i < 10000; i++ {atomic.AddInt32(&total, 1)}
}func sub() {defer wg.Done()for i := 0; i < 10000; i++ {atomic.AddInt32(&total, -1)}
}
RWMutex 读写锁
锁本质上就将并行的代码串行化,使用lock会影响性能。即使是设计锁,那么也应该保持并行。
我们有两组协程,其中一组负责写数据,另一组负责读数据,web系统中绝大部分场景都是读多写少。虽然有多个gorounte,但是仔细分析我们会发现读是可以进行并发,读和写应该进行串行。我们在读的时候不能写,在写的时候不能读。
这里我们就出现了读写锁m我们在进行读写锁的时候,我们需要将写操作的时候添加写锁:
- 写锁会防止别的写锁获取和读锁获取,使用WaitGroup
- 读锁不会阻止别人的锁,写锁会阻止别人的锁。
for i := 0; i < 5; ++i {go func() {defer wg.Done()for {rwlock.RLock() // 加读锁,读锁不会阻止别人的读// TODOrwlock.RUnlock()}}
}
使用channel进行gorounte之间的通信
channel通道
在Go语言中不要通过共享内存进行通信,而是要通过通信来实现内存共享
在C++中如何实现进程之间的通信,就是使用一个全局变量(两个线程都可以看到的)来实现通信,在其他语言中的多线程编程的时候,两个gorountine之间通信最常用的方式是channel,再加上语法糖让channel更加简单。
channel初始化值为0,放值进去会阻塞。
func main() {var msg chan string // 定义一个通道msg = make(chan string, 1)msg <- "加油"data := <- msgfmt.Println(data)
}
静态语言中使用channel,我们需要指明通道中的类型是什么??注意箭头的指向,如果定义的通道在箭头的左边,则是将数据放入到通道中,如果定义的通道在箭头的右边,表示从通道中取数据。
channel有缓冲和无缓冲
var msg chan stringmsg = make(chan string, 0) // channel的初始值如果为0的话,你放值进去会进行阻塞go func(msg chan string) {// go语言中有一种 happen-before机制,可以保证线程在channel中有值才会进行data := <- msgfmt.Println(data)
}(msg)msg <- "加油旭杏" // 放值到channel中
time.Sleep(time.Second * 10)
无缓冲区channel适用于 通知,B要第一时间知道A是否完成
有缓冲区channel适用于消费者和生产者之间的通信
go中channel的应用场景
- 消息传递,消息过滤
- 信号广播
- 事件订阅和广播
- 任务分发
- 结果汇总
- 并发控制
- 同步和异步
在默认情况下,channel是双向的,但是我们经常使用channel作为参数进行传递,希望对方是单向使用的。 双向channel可以赋值给单向channel,但是单向channel不能赋值给双向channel,代码如下:
var ch1 chan int
var ch2 chan<- float64 // 单向channel,只能写入数据
var ch3 <-chan int // 只能读取数据
我们需要进行通信,就需要进行
通过channel实现交叉打印
我们需要使用channel进行打印,我们使用channel去进行通知,好像信号量,就是我们先打印数字然后唤醒打印字符的,在去打印字符,打印完字符再去唤醒打印数字的,如此交替执行。
监控gorounte的执行
在go语言中,select类似于switch case 语句,但是select的功能和我们操作Linux里面提供的io的select,poll,epoll不一样,select主要作用于多个channel。
现在有一个需求,我们现在有两个gorounte正在执行,但是我的主的gorounte中,当某一个执行完成之后,这个时候我们会立马知道
相关文章:
【Go语言】
type关键字的用法 定义结构体定义接口定义类型别名类型定义类型判断 别名实际上是为了更好地理解代码/ 这里要分点进行记录 使用传值的例子,当两个类型不一样需要进行类型转换 type Myint int // 自定义类型,基于已有的类型自定义一个类型type Myin…...
【Spring Boot】元注解
元注解 1.元注解1.1 Target1.2 Retention1.3 Inherited1.4 Documented1.5 interface 2.自定义注解2.1 创建自定义注解类2.2 实现业务逻辑2.3 使用自定义注解 1.元注解 元注解就是定义注解的注解,是 Java 提供的用于定义注解的基本注解。 注解 说明 Retention是注解…...
基于信号分解和多种深度学习结合的上证指数预测模型
大家好,我是带我去滑雪! 为了给投资者提供更准确的投资建议、帮助政府和监管部门更好地制定相关政策,维护市场稳定,本文对股民情绪和上证指数之间的关系进行更深入的研究,并结合信号分解、优化算法和深度学习对上证指数…...
基于Spring Boot的酒店住宿管理平台
1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理酒店客房管理系统的相关信息成为必然。开发…...
游聚对战平台 三国战纪2012CE修改器修改地址
游聚对战平台 三国战纪2012比较全的一次地址。 工具 ce修改器 自行百度下载 1袖箭 2褐色鸡蛋 3毒堂 4飞盘 5火焰弹 6绿色鸡蛋 7金珠 8毒蝎 9毒镖 10铁莲花 11张陵剑 12张角巾 13太清丹经 14黄石公 15九节杖 16隐身衣 17神仙笔 18 玉蜂术(效果不明)19天师…...
Qt Creator中的项目栏
shadow build: [基础]Qt Creator 的 Shadow build(影子构建)-CSDN博客 影子构建:将源码路径和构建路径分开(生成的makefile文件和其他产物都不放到源码路径),以此来保证源码路径的清洁。 实验1: 我创建了两个项目:…...
keepalived+web 实现双机热备
环境:利用keeplived实现web服务器的双机热备(高可用) 注意: (1) 利用keeplivedweb做双击热备(高可用),最少需要两台服务器,可以实现多域名对应一个VIP,并且访问不同域名,显示不同主页…...
关于python的import
在Python中,import语句用于导入其他模块或模块中的特定部分,以便在代码中使用它们。这就可以重用代码,而不是每次都从头开始编写所有的功能。 基本用法 导入整个模块: import module_name 例如: import math print(…...
帕金森后期吞咽困难:破解难题,重拾生活美味!
在这个快节奏的时代,健康成为了我们最宝贵的财富。然而,对于帕金森病患者及其家庭而言,随着病情的进展,尤其是进入后期阶段,吞咽困难成为了他们不得不面对的严峻挑战。今天,就让我们一起走进这个温暖而坚韧…...
android 添加USB网卡并配置DNS
工作需要,需要使用TBox分享的网络,Android将TBox当作一个USB网卡,接下来就简单了,配置这个网卡的信息即可。 加载默认网卡的信息在frameworks/opt/net/ethernet/java/com/android/server/ethernet/EthernetTracker.java中 Ethern…...
【面试经典150】day 8
#1024程序员节 | 征文# 作为一个未来的程序员,现在我要继续刷题了。 力扣时刻。 目录 1.接雨水 2.罗马数字转整数 3.最后一个单词的长度 4.最长公共前缀 5.反转字符串中的单词 1.接雨水 好好好好好好,一开始就接雨水。我记得接了n次了。。。 痛苦战…...
Python -- 网络爬虫
Python – 网络爬虫 流程: 1. 连接链接获取页面内容(html文件); 2. 过滤获取需要信息(正则) [可能重复步骤1,2] ; 3. 存储文件到本地。一)网络连接获取页面内容 # 网络…...
【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-5
文件下载与邀请翻译者 学习英特尔开发手册,最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册,会是一件耗时费力的工作。如果有愿意和我一起来做这件事的,那么ÿ…...
设计模式4 适配器 (adapter)
一句话,适配器按照客户的需求, 适配当前已有的接口。 目标接口:reqeust() public interface Target {void request(); //this is client needed interface }已有接口:specificRequest package com.example.adapter;import android.uti…...
《分布式机器学习模式》:解锁分布式ML的实战宝典
在大数据和人工智能时代,机器学习已经成为推动技术进步的重要引擎。然而,随着数据量的爆炸性增长和模型复杂度的提升,单机环境下的机器学习已经难以满足实际需求。因此,将机器学习应用迁移到分布式系统上,成为了一个不…...
【项目实战】HuggingFace初步实战,使用HF做一些小型任务
Huggingface初步实战 一、前期准备工作二、学习pipline2.1.试运行代码,使用HuggingFace下载模型2.2. 例子1,情感检测分析(只有积极和消极两个状态)2.3. 例子2,文本生成 三、学会使用Tokenizer & Model3.1.tokenizer(分词器&am…...
堆的应用——堆排序和TOP-K问题
1.堆排序 想法⼀: 基于已有数组建堆、取堆顶元素完成排序。也就是利用写好的堆数据结构(之前的文章有讲解),去实现排序。 void HeapSort(int* a, int n){HP hp;for(int i 0; i < n; i){HPPush(&hp,a[i]);}int i 0;whi…...
探秘 MySQL 数据类型的艺术:性能与存储的精妙平衡
文章目录 前言🎀一、数据类型分类🎀二、整数类型(举例 TINYINT 和 INT )🎫2.1 TINYINT 和 INT 类型的定义2.1.1 TINYINT2.1.2 INT 🎫2.2 表的操作示例2.2.1 创建包含 TINYINT 和 INT 类型的表2.2.2 插入数据…...
使用任意绘图软件自学并结合上课所学内容完成数据库原理图绘制
本次绘图采用亿图图示软件...
static、 静态导入、成员变量的初始化、单例模式、final 常量(Content)、嵌套类、局部类、抽象类、接口、Lambda、方法引用
static static 常用来修饰类的成员:成员变量、方法、嵌套类 成员变量 被static修饰:类变量、成员变量、静态字段 在程序中只占用一段固定的内存(存储在方法区),所有对象共享可以通过实例、类访问 (一般用类名访问和修…...
基于SSM的智能养生平台管理系统源码带本地搭建教程
技术栈与架构 技术框架:采用SSM(Spring Spring MVC MyBatis)作为后端开发框架,结合前端技术栈layui、JSP、Bootstrap与jQuery,以及数据库MySQL 5.7,共同构建项目。 运行环境:项目在JDK 8环境…...
Latex中文排版字体和字号
中文排版 最近常用latex排版,也遇到了很多问题。这里对于主要的参考文章做一个总结和推荐。 一份不太简短的 LaTeX2ε 介绍【中文资料】ctex宏包用户手册,用户手册使用 命令行texdoc ctex 这两个文档都是中文的,而且几乎解决了我90%的排版…...
[C++ 11] 列表初始化:轻量级对象initializer_list
C发展历史 C11是C语言的第二个主要版本,也是自C98以来最重要的一次更新。它引入了大量的新特性,标准化了已有的实践,并极大地改进了C程序员可用的抽象能力。在2011年8月12日被ISO正式采纳之前,人们一直使用“C0x”这个名称&#…...
【NodeJS】NodeJS+mongoDB在线版开发简单RestfulAPI (八):API说明(暂时完结,后续考虑将在线版mongoDB变为本地版)
本项目旨在学习如何快速使用 nodejs 开发后端api,并为以后开展其他项目的开启提供简易的后端模版。(非后端工程师) 由于文档是代码写完之后,为了记录项目中需要注意的技术点,因此文档的叙述方式并非开发顺序࿰…...
manictime整合两个数据库的数据
作用 老电脑崩溃了,有个1t.db, 新电脑有个3t.db 那么重装系统后就想整合起来用。 整合前文件大小 整合命令 .\mtdb.exe importtimelines -sdbpa ManicTimeCore-1t.db -dbpa ManicTimeCore-3t.db -tt ManicTime/ComputerUsage,ManicTime/Applications,ManicTime…...
Spring Boot植物健康系统:智慧农业的新趋势
6系统测试 6.1概念和意义 测试的定义:程序测试是为了发现错误而执行程序的过程。测试(Testing)的任务与目的可以描述为: 目的:发现程序的错误; 任务:通过在计算机上执行程序,暴露程序中潜在的错误。 另一个…...
(三)第一个Qt程序“Qt版本的HelloWorld”
一、随记 我们在学习编程语言的时候,各种讲解编程语言的书籍中通常都会以一个非常经典的“HelloWorld”程序展开详细讲解。程序虽然简短,但是“麻雀虽小,五脏俱全”,但是却非常适合用来熟悉程序结构、规范,快速形成对编…...
【Python知识】一个强大的数据分析库Pandas
文章目录 Pandas概述1. 安装 Pandas2. 基本数据结构3. 数据导入和导出4. 数据清洗5. 数据选择和过滤6. 数据聚合和摘要7. 数据合并和连接8. 数据透视表9. 时间序列分析10. 数据可视化 📈 如何使用 Pandas 进行复杂的数据分析?1. 数据预处理2. 处理缺失值…...
10.26学习
1.整形的定义和输出 在C语言中,整形(Integer)是一种基本数据类型,用于存储整数。整形变量可以是正数、负数或零。在定义和输出整形变量时,需要注意以下几点: ①定义整形变量: 使用 int 关键字…...
CSS易漏知识
复杂选择器可以通过(id的个数,class的个数,标签的个数)的形式,计算权重。 如果我们需要将某个选择器的某条属性提升权重,可以在属性后面写!important;注意!importent要写在;前面 很多公司不允许…...
百度注册域名免费建站/如何做一个网页
1. ODBC 插件使用场景 在使用 DolphinDB 的业务场景中,我们有从其他数据源和 DolphinDB 之间同步数据的需求。比如从 Oracle 读数据写入到 DolphinDB,或者从 DolphinDB 写数据到 Oracle 数据库。 按照频率的不同,数据同步可以分为实时和离线…...
汕头免费建设网站制作/百度网盘app怎么打开链接
👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇转自 | 募格学术参考资料 | 抖音陈见夏夏(求关注版、秒闻视频、募格学术读者投稿、留言、微博、知乎等。试问谁没有为导师的论文批注心跳加速过呢…...
青岛移动网站开发/大一网页设计作业成品
Appium server Capabilities传递参数 Android 特定 参考:http://appium.io/slate/cn/master/android 特有关键字描述实例appActivity你要从你的应用包中启动的 Android Activity 名称。它通常需要在前面添加 . (如:使用.MainActivity 而不是 MainAct…...
wordpress 首页访问量/域名解析ip地址查询
原本这是《关于ASP.NET Routing的几点内容》一文中的一节,不过等写完这节之后发现这块内容已经比较完整了,而且它本身也是独立和最为常见的部分,因此我把它提取出来单独成文。至于那片文章的其他部分我会再修改一下,明天发布。希望…...
江门站官网/写一篇推广商品的软文
生活中虽然有难过的事情,但是要微笑面对哦!下面是由出国留学网编辑为大家整理的“关于难过的作文400字”,仅供参考,欢迎大家阅读。关于难过的作文400字(一)星期六下午,我到妈妈的“第一时间”快餐店的办公室玩…...
北京建设教育协会网站/做了5天游戏推广被抓了
第一次安装JDK1.5,使用Eclipse,毫无问题。后为了改变JDK1.5安装路径故卸载重装,然后就发现用不了; 让我去.metadata/.log查看; !SESSION 2013-10-03 09:39:56.500 ----------------------------------------------- ec…...