password
tags
type
status
date
slug
summary
category
icon
一、Go开发环境搭建
前提:本地安装Goland即可,记得在IDE中配置代理对象https://goproxy.io,本地无需手动安装GoSDK,在IDE命令行使用
常用命令
二、基本数据类型和复合类型
基本类型变量声明
数值类型转换
在Java中支持自动类型转换,例如
但是这样将会降低代码可读性,也有可能出现转换错误,Go语言设计从可读性出发不允许变量之间转换 当类型不一致时候就必须要进行显示转换
字符串、数值转换
复合类型变量声明
指针类型
数组
键值对
切片
结构体
函数
接口
管道
三、代码块和流程控制
if循环
for循环
标准写法,和其他语言类似,关键字break、continue同样可用,不再赘述
迭代器写法,数组迭代(有序)和映射迭代(无序)
四、函数
函数即值
匿名函数
闭包
延迟函数defer
五、指针
每个变量都被存储在一个或多个连续的内存地址,我们称之为地址 &是地址运算符。它位于值类型的变量之前,并返回存储该值的内存地址。 *是间接寻址运算符。它位于指针类型的变量之前,并返回所指向位置的值。 指针类型是指指针的类型。指针类型可以基于任何类型,类型名称前加*来表示
结构体变量前使用&创建结构体实例,但是无法在字面量或常量使用&,因为他们没有内存地址,只在编译期存在。使用辅助函数可以将常量值变成指针。指针即可变的参数,大多数情况下应该是用值,这样更容易理解数据是如何被修改 指针传递可提高性能,如果结构体足够大,使用结构体的指针作为输入参数或返回值可以提升性能。对于所有数据大小来说,将指针传入函数的时间是恒定的,受硬件影响
六、垃圾回收
垃圾回收器的工作就是自动检测未被使用的内存,并将其回收,以便重新使用。
栈是一个连续的内存块,执行线程中的每个函数调用都共享同一个栈。栈指针跟踪最后分配内存的位置,通过移动栈指针来分配额外的内存。当一个函数被调用时候,为该函数创建一个新的栈帧。局部变量与传入函数的参数一起被存储在栈中。当一个函数退出时,它的返回值通过栈复制到回调用函数,栈指针被移回到退出函数的栈帧的开头,并释放所有被该函数的局部变量和参数使用的栈内存
七、类型、方法与接口
与大多数编程语言很不相同
Go是一种静态类型语言,有内置类型和自定义类型。像大多数现代语言一样,Go也允许将方法附加到类型上,而且也有具体语言的抽象。允许我们编写调用方法的代码,而不需要关心具体实现。Go的设计鼓励组合,避免继承的理念。
Go语言的类型
方法
方法和函数的区别
逻辑只依赖于输入参数,那么应该定义为一个函数
类型声明不是继承
内嵌不是继承
接口概览
Go设计的真正亮点是隐式接口,是Go中唯一抽象类型具体类型的方法集包含接口方法集中的所有方法,那么该具体类型就实现了该接口
像一个类型可以内嵌到一个结构中一样,一个接口内嵌到一个接口中
接收接口,返回结构体
返回一个结构体避免了堆分配,但是当调用一个带接口类型参数的函数时,会对每个接口参数进行堆分配。
接口与nil
nil,指针类型的零值,一个接口被认为是nil则其类型和值必须都是nil
在Go运行时,接口被实现为一对指针,其中一个指向底层类型,一个指向基础值。类型非空,那么接口就是非空的。
空接口
在静态语言中,需要一种方法来说明变量可以存储任何类型的值,这就是interface{},any就是空接口
类型断言
八、错误
处理错误
在go语言中,错误是一个interface类型,那就意味着错误不处理可以返回nil交给上游处理
处理错误的时候常用errors包,如下
或使用fmt.Errorf()函数,支持格式化占位符并返回error类型
panic和recover
在go中,程序运行过程中出现错误且未做处理,当前运行的程序会立即退出且执行完所有defer函数,该函数的外层调用中的defer也会执行,直至到主函数,接着程序会
完全退出
,并在控制台打印错误栈信息,例如切片访问越界运行控制台出现
panic: runtime error: index out of range [100] with length 10
可以在defer函数中调用recover()判断是否有panic发生,处理异常就可以让程序继续运行了,
注意错误的函数遇到panic()即使恢复也不能执行非defer函数,因为恢复是在defer函数中处理的
九、模块、包和导入
仓库、模块和包
Go中的库管理依赖于三个概念:仓库、模块和包。仓库是一个通用的概念,项目的源代码通过版本控制存储在仓库之中。模块是Go库或应用程序的根目录,存储在仓库中。模块包含一个或多个包,用来组织模块的结构
go.mod
go mod init命令创建go.mod文件,当前所在目录就是模块根目录。模块路径是区分大小写的,不要在模块路径中使用大写字母
十、Go并发
Go语言的并发通过
goroutine
实现,还提供channel
在不同goroutine间进行通信。goroutine和channel是Go语言秉承的CSP(Communicating Sequential Process
)并发模式的基础goroutine
在java或c++中,我们要实现并发编程的时候,我们需要维护人工维护一个线程池,但是go在语言层面原生支持
轻量级线程
即协程
,无需手动维护,使用go
关键字表示开启一个新的协程交替执行,即并发执行
channel
channel
是goroutine之间通信的数据,是一种引用类型
,通过通道共享内存声明
初始化
操作
通道有发送、接收、关闭
并发安全和锁
并发不安全操作
互斥锁
读写互斥锁
适合读多写少场景提升效率
并发安全map
sync.Map
是并发环境安全的map,这个类似于java中的ConcurentHashMap
,支持Load
Store
LoadOrStore
LoadOrDelete
等方法,确保此操作原子性单例模式
加载配置存在失效场景
以上代码在并发场景存在2个问题
协程A执行loadConfig()对map初始化但未put数据
同时协程B返回map中get的值
,那么导致上游查询结果为nil,导致业务错误
loadConfig()被多次执行
,map[string]any在并发操作场景不安全导致出现panic
为了解决以上问题,确保
loadConfig函数只加载一次
,那么可以使用double check + 互斥锁
来保证函数只初始化一次但是上续代码依旧存在
问题1
,我们可以增加一个bool量进行判断,问题得到解决以上是我们手动实现了一个
单例模式只加载一次的场景
,我们可以对我们的保证加载一次的函数进行封装,函数签名如下获取getConfig函数可修改为以下代码,自测通过
在
sync
包下提供Once
,可以实现函数全局加载一次的效果十一、Go标准库
io库
time
encoding/json
net/http包
总结
十二、上下文
十三、测试
十四、恶龙禁区:反射、unsafe和cgo
在运行时使用反射处理类型
反射可以在程序运行时查看类型,提供了运行时检查、变更和创建变量。
类型、类别和值
标准库中reflect包提供了所有类型和函数反射相关的所有实现。反射由三个概念组成:类型、类别和值。类别(如struct)包含具体类型。
十五、Go范型
十六、Web项目脚手架
前言
基于https://github.com/gnimli/go-web-mini 项目学习Web项目单体架构
包结构
核心文件
核心代码
- Author:武帅祺
- URL:https://qqqi.top//article/40f90a86-6da8-428f-b480-a8afc3288c5a
- Copyright:本文章为原创内容,版权归作者所有。如需转载,请联系我,谢谢!