当前位置: 首页> 科技> 数码 > go 笔记

go 笔记

时间:2025/7/28 5:36:54来源:https://blog.csdn.net/qq_41834780/article/details/142137982 浏览次数:0次

数据结构与 方法(增删改查)

  1. 安装goland,注意版本是2024.1.1,不是2024.2.1,软件下载地址也在链接中提供了

  2. ‘go’ 不是内部或外部命令,也不是可运行的程序
    或批处理文件。

在 Windows 搜索栏中输入“环境变量”,然后选择“编辑系统环境变量”或“编辑环境变量”。
在系统属性窗口中,点击“环境变量”按钮。
在“系统变量”区域,找到并选择“Path”变量,然后点击“编辑”。
在弹出的窗口中,点击“新建”,然后输入 Go 的 bin 目录的路径,例如 C:\Go\bin。
点击“确定”保存更改。

  1. 枚举用 iota自动就依次排号变成枚举了,不用你赋值了。枚举就是变量代替正整数
    有类型的枚举的话,就不能 float64+ int了,因为有严格的类型校验,没指明类型的可以

  2. 字符串拼接可以用 +

数据不可变,它的值改变不了
字符串不可变: 意味着你不能改变字符串内部的单个字符。
变量可变: 变量本身可以被重新赋值,指向另一个字符串。

var newName string
newName = name + " " + "day"
fmt.Println(newName)
newName += "s"
fmt.Println(newName)

从行为上看,newName 的内容变了,但这是因为你指向了一个全新的字符串。在 Go 中,这种操作不是修改原有字符串,而是创建了一个新的字符串,并让 newName 指向这个新的字符串。原有的字符串 “lucky day” 仍然存在于内存中,直到 Go 的垃圾收集器决定回收它。

  1. 结构体就是复合类型的聚合
    指针,如果p = &s(结构体) ,通过取地址运算符取到指针, 那么p就能像 s一样点出来所有内含的字段
  2. 数组

长度固定,存储同一类型的数据。数组是值传递的,不是引用传递,每次作为参数都是值传递,数组太大,复制会引起性能损耗。解决方案就是使用切片

切片  【指针,len, cap容量     cap>=len】

可以动态改变长度(每次大于容量再append元素,容量是翻倍的涨,比如1,2,4,8),一旦扩容,切片就会和原数组解绑,然后绑定到一个新数组上。频繁扩容耗费性能。所以初始化的时候,len可以设置为0,但是容量最好设置一个预估的值
len就是切片里元素的个数,
切片是对底层数组的描述的意思是当改动切片中的某个值,从切片用中括号截取的切片对应的值也会改变,它从根上就变化了。
容量cap就是你把原切片切出一部分,容量就是原容量减去中括号前面切去的就是现在的容量

  1. golang是编译语言,python是脚本语言

脚本语言:适用于快速开发、自动化任务、Web开发和应用程序扩展。它们的价值在于提高开发效率和灵活性。
编译语言:适用于高性能应用、系统编程、大型企业应用和安全性要求高的场景。它们的价值在于提供高效的执行速度和对底层系统的控制。

  1. make 只能用于内置的切片、映射和通道类型,不能用于用户定义的类型或其他内置类型(如整型、浮点型等)。对于这些类型,你需要使用其他方式(如直接初始化或使用 new 函数)来创建和初始化变量。

  2. map 哈希表或者字典,k-v。
    遍历map的时候是无序的。map也是有容量的,如果频繁扩容也会造成性能消耗

  3. 切片(slice)、映射(map)和通道(channel)是引用类型,其他的是值类型

  4. 这里num的作用域就是if 函数内。err经常用这一招
    在这里插入图片描述

  5. for循环重复执行一段代码,直到不满足条件为止
    for range用来遍历 切片 map 数组,string 等用的,下面是range和传统形式两种
    []string{“lucky”,“nike”,“allen”}中括号里没东西就是切片,有数值就是数组
    在这里插入图片描述

  6. 包就是import那个,

package中 首字母大写的函数是可以被导出的,首字母小写的就是内部使用的

构建就是 go build xx.go,xx.go就是你的那个package xx脚本。然后就可以在命令行直接执行 ./xx 跟 go run xx.go一样的效果

如果有两个errors包(不需要go build的,脚本形式就行),只需要前面加上来源,比如github.com/pkg/errors,并且给它取个别名来解决包冲突

包名一般跟顶层文件夹名保持一致

交叉编译(Cross-Compilation)是指在一种平台上编译生成能够在另一种平台上运行的程序。也就是说,编译代码的机器和运行该代码的目标机器使用不同的操作系统或硬件架构。交叉编译通常用于开发需要在多个平台(如 Linux、Windows、macOS,或不同的处理器架构如 ARM、x86)上运行的程序。
Go 语言内置了对交叉编译的强大支持。Go 的编译器允许开发者通过设置两个环境变量 GOOS(目标操作系统)和 GOARCH(目标硬件架构)来进行交叉编译。

例如,想要在 Linux 上编译一个能在 Windows 运行的程序,开发者可以这样做:

GOOS=windows GOARCH=amd64 go build -o myapp.exe

同理,想要编译一个能在 ARM 架构的 Linux 设备上运行的 Go 程序,可以设置:

GOOS=linux GOARCH=arm64 go build -o myapp
  1. 函数
    func init(){}
    func 函数名(参数)(返回值){
    函数体
    defer 函数:当前函数结束时候调用 //主要用于释放资源。因为中间函数发生错误,return掉了,这时就没法执行关闭资源的代码,这时候defer就能派上用场了。比如ioutil.ReadAll(file)的时候,需要 file.Close()
    }

  2. 方法
    相较于函数,多了一个 接收者 receiver,用来连接方法与类型,比如结构体的方法,不能是基础类型,int,string这些
    receiver参数可以是值类型(用于只读),也可以是指针类型(读写)。
    在这里插入图片描述
    在这里插入图片描述

  3. 接口,里面有没有实现的方法。我开放了我的系统,但你实现要符合我的规则,也就是接口
    在这里插入图片描述
    接口组合就是 接口套接口或者 结构体里面套接口

  4. 并发与并行
    同时运行多个任务,交替进行,不一定在同一时刻都在运行的是并发。 都在同一时刻运行的是并行。并行需要多核cpu或者分布式计算系统

并行那么棒,为啥需要并发
1)并发可以让 I/O 操作等待的时间里去做其他事情(其他协程或者线程切进来工作)。比如在等朋友的时候,你还可以玩玩手机,不是干等。
2)防止死锁

协程

用了协程,干一件事用10ms,干5件事也是10ms

创建协程,使用WaitGroup 等待协程结束(防止协程还没执行,main函数先执行完了,就都结束了)

解决并发同时访问一个资源不安全的问题,用mutex.Lock() 互斥锁。访问的时候变成了串行。锁的位置要放准,锁太多执行效率会下降

  1. channel 两个协程通信,生产者 消费者模型
    数据写进channel,然后从channel里面读出来
    ch:=make(chan int, 3) 这个3就使 channel变成有缓冲的了,这样有空间就往里面写。否则只能写一个,读一个,变成串行了,有缓冲就并发,处理快得多

如果无缓冲,又没人读,就变成死锁,报错,解决就是用 select。它监听多个channel,谁有数据时,就执行对应 case 分支
收发都有select。

channel 还可以执行上报心跳

  1. error 处理 可预期的、可以处理的错误
    透明错误 – 什么问题报什么
    哨兵错误 – 比如搜数据库没有这条数据,就写入,用户看不到的,后台就把这个错误解决了
    自定义错误 – error 中包含 错误码,追踪 id 等等
    行为错误 – 给错误分组。比如网络错误,连接错误。对应分组有相应的应对方式

  2. panic 适用于 不可恢复的错误


二、project

在这里插入图片描述

  1. Gin web框架(启动个后端,监听8080端口),在GitHub上有 安装和简单示例
    postman可以测试它的接口
  2. 路由
    Gin提供了 增删改查(PUT PATCH POST…) 等 用于处理 HTTP

CMS 内容管理
对应/api/cms/各种路由,api会单独拎出来

main函数加载路由表,route对应的url,而 services对应的是url对应的处理方法

  1. 中间件 剥洋葱
    在请求被处理前后做一些额外的操作
    比如 session 鉴权,就是postman带个session id

  2. 模型绑定与验证 自动转换
    将json转换为我们在go语言中定义的结构体
    结构体的字段与json中的字段一一映射。这个往往是请求和响应两个结构体成对出现的,和客户端有来有回

  3. 注册接口
    在这里插入图片描述
    后端定义POST 注册接口 + handle 处理逻辑

密码加密 避免暴力破解

1)生成随机盐值,纵使输入相同的密码,得到的哈希值也是不同的
2)内部多次哈希的迭代次数就是工作因子
3)这样通过密码 存储的盐值和工作因子,就能验证密码是否正确

database tool

goland自带的工具,连接数据库,操作数据库
user.sql里面包含着表要创建成什么样子,就是sql语句的合集

在 Go 语言中,DAO(Data Access Object)模式是一种设计模式,主要用于将应用程序与底层数据存储(例如数据库)的交互逻辑分离。DAO 层负责处理与数据库的所有操作,如 CRUD(创建、读取、更新、删除)等。

GORM

就是go 的 ORM (对象关系映射)。数据库操作用的
用结构体映射数据库中的表,元素等。跟前端那个映射类似

先连上表,再增删改查

分表用重写TableName
分页查询用链式调用。比如 db.Where().Offset().Limit().Find()

model里面就是结构体们

  1. 登录接口
    在这里插入图片描述
    登录成功 返回session id,并且session id持久化

redis

github上有 go-redis
也可以通过命令行redis-cli 登进去看

redis存了两个,一个是 userid : sessionid. 另一个是session_auth:sessionid : time.Now().Unix(),这个是鉴权用的

session id

用 go get github.com/google/uuid 这个库生成 session id := uuid.New().String()

鉴权

带着sessionID去访问,如果session_auth还在的话,就能通过鉴权,不用输入用户名和密码,直接进去

  1. 内容库
    在这里插入图片描述
    goland编辑器右键自带单元测试。验证写得函数是否正确,省的每次还得开关整个服务

查询的时候涉及到翻页逻辑

比如查哪个id,作者,title,查找范围是第几页的前多少个数据,这是前端传过去的。后端就会返回回来具体内容

  1. 加工流

在 Go 语言中,DAG(Directed Acyclic Graph, 有向无环图) 是一种数据结构,用于表示具有方向性的、无环的图形。它常被用于表示依赖关系、任务调度、数据流等问题,特别适合在分布式系统、工作流调度、数据处理流水线等场景中。
GoFlow 是 Go 语言中的一个框架,它利用 DAG 来处理数据流问题。它的主要功能是通过 DAG 来定义和执行一系列具有依赖关系的任务,使得数据能够沿着这些任务进行流动,帮助开发者轻松管理复杂的依赖关系和任务调度。

go get github.com/s8sg/goflow
Input —> 累加 1到10 —> 累加 100到200 —> output。
redis用于工作流临时存储
在这里插入图片描述

上面是简单的,下面是个更复杂的加工流

在这里插入图片描述
做两次累加(它们是并行,异步执行的,不一定谁先),需要都完成之后,再执行聚合的逻辑。直接调现成的方法完成聚合
也提供了条件分支现成的方法

  1. 自己项目的dag加工流
    在这里插入图片描述
    thumbnail是缩略图

加工流和内容创建是如何结合起来的呢?


三、微服务

大应用拆分成一组小型、自治的微服务
服务用http,rpc 通信

中间件

划分了微服务,但也需要中间件在中间辅助

  1. 服务注册与发现。注册进去,别人想通信就能发现
    在微服务架构中,服务实例是动态的,它们可能随时上线、下线、扩缩容,因此它们的 IP 和端口会经常变化。如果没有注册中心,其他服务将无法知道这些变化,导致通信失败。
    注册中心可以定期检查服务实例的健康状况。如果某个服务实例宕机或不可用,注册中心会从服务列表中移除它,防止向其发送请求。
  2. 负载均衡:资源调度均衡
  3. API 网关,入口,根据path分发给不同的后端服务
  4. 消息队列,我把任务发出去,不关心谁来处理。谁关心谁就去处理
  5. 分布式缓存,比如多个后端服务公用一个缓存,后端服务又在不同的机器上
  6. 日志与监控

在这里插入图片描述
上图说明
该架构图展示了一个通过负载均衡器进行流量管理的系统,涉及到网关、内容管理、内容加工、注册中心、分布式缓存、日志监控等多个模块。具体解释如下:

  1. 网关:最外层的组件,负责处理来自外部的请求。网关会将请求转发到内部的不同服务,通常用来做统一入口管理、负载均衡和安全策略。

  2. 负载均衡器:网关接收到请求后,通过负载均衡器将流量分发到多个实例,以提高系统的处理能力。这个模块负责根据流量和服务的健康状况将请求分发到不同的“工作节点”(work)。

  3. 内容管理和内容加工

    • 内容管理:负责管理内容的增删改查功能,通常用于处理用户请求中的内容操作。它会分发到不同的“工作节点”(work 1, work 2, work 3),这些节点可能是多个副本,处理并行任务来分担负载。
    • 内容加工:可能是对内容进行一些预处理或转换的模块。同样会分发任务给多个工作节点,以处理大量并发任务。
  4. 注册登录:系统的用户登录注册模块,这个模块也有多个工作节点来提供服务,通常与内容管理交互。

  5. 注册中心:注册中心可能是服务发现的模块,允许不同服务在集群中找到彼此的位置,确保服务间通信的正常进行。它是整个系统的中枢,确保不同模块之间的依赖关系。

  6. 分布式缓存:用于缓存数据,降低数据库的访问压力,提高系统性能。缓存可以加快频繁读取的内容的访问速度,减少对后端数据库的依赖。

  7. 日志与监控:这是系统的监控模块,负责记录日志和系统运行情况,帮助开发者和运维人员了解系统的健康状况,进行故障排查和性能分析。

  8. 消息队列:消息队列位于系统的最右侧,用于在模块之间传递消息。消息队列可以确保消息异步处理,提供可靠性和削峰填谷功能,常用于解耦系统的不同部分。

整条链路的流程可以总结为:
用户请求通过网关进入系统,经过负载均衡器,将请求分发到不同的工作节点进行处理(注册登录、内容管理、内容加工等)。这些节点依赖注册中心进行服务发现,并且利用分布式缓存加快访问。处理完成后,通过消息队列进行异步通信和日志记录,同时监控系统的健康状况。

这样设计的系统具有高扩展性、负载均衡能力强,支持分布式缓存和异步消息处理,适合大规模并发请求的场景。

RPC

RPC(Remote Procedure Call,远程过程调用)是一种让不同计算机上的程序像调用本地函数一样进行通信的技术,它解决了跨网络调用远程服务的复杂性。通过RPC,程序可以很容易地调用其他机器上的函数,而不必关心底层网络通信细节。

RPC 解决的问题:

  1. 隐藏了网络通信的复杂性
    通常,程序要在不同机器之间通信,需要处理网络连接、序列化数据、发送请求、接收响应等复杂步骤。RPC 将这些步骤隐藏起来,开发者只需调用函数,RPC 底层会自动完成数据的发送和接收。

  2. 让分布式系统的调用像本地调用一样简单
    在本地,调用函数只需要传入参数,得到返回值。RPC 模拟了这种方式,开发者可以用相同的方式调用远程函数,不需要手动处理跨网络的通信。

  3. 简化了跨服务通信
    在微服务或分布式系统中,服务通常分布在多个不同的机器上。RPC 提供了标准的调用方式,使得各个服务之间的通信变得简单、统一。

例子解释:

想象一下,你有两个程序,一个运行在电脑A上,一个运行在电脑B上。电脑A上的程序想调用电脑B上的某个函数。如果没有RPC,电脑A的程序要这么做:

  1. 打开一个网络连接,连接到电脑B。
  2. 将要调用的函数名称和参数手动打包(序列化)成网络消息。
  3. 将消息发送到电脑B。
  4. 等待电脑B处理请求。
  5. 接收到电脑B的响应后,再把返回结果解析出来(反序列化)。
  6. 关闭网络连接。

RPC 让这一切变得简单

  • 你只需要像在本地一样调用函数:result = some_function(params)
  • RPC 框架会自动处理所有的底层细节:它会在电脑A和电脑B之间建立连接,传递参数,调用电脑B上的函数,获取结果并返回给你。

举例:gRPC(现代RPC实现)

在微服务架构中,gRPC 是一种流行的 RPC 框架。比如,假设你有一个订单服务和一个支付服务:

  • 当用户下单时,订单服务需要调用支付服务处理付款。
  • 使用 gRPC,订单服务就像调用本地函数一样简单地调用支付服务:payment_result = process_payment(order_details)
  • 实际上,gRPC 会在订单服务和支付服务之间建立网络连接,发送订单信息,等待支付服务处理,并返回支付结果。

总结:

RPC 通过隐藏底层的网络通信细节,让开发者可以像调用本地函数一样轻松地调用远程服务。这大大简化了分布式系统和微服务之间的交互,提升了开发效率。

kratos 开源微服务框架 哔哩公司的

关键字:go 笔记

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: