wohu007
这个作者很懒,什么都没留下…
展开
-
Go 学习笔记(90)— 常用设计模式(单例模式、工厂模式、策略模式、模板模式、代理模式、选项模式)
从总体上说,设计模式可以分为创建型模式、结构型模式、行为型模式 3 大类,用来完成不同的场景。其中分类如下:1. 创建型模式它提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这种类型的设计模式里,单例模式和工厂模式(具体包括简单工厂模式、抽象工厂模式和工厂方法模式三种)在 Go 项目开发中比较常用。1.1 单例模式单例模式,是最简单的一个模式。在 Go 中,单例模式指的是全局只有一个实例,并且它负责创建自己的对象。单例模式不仅有利于减少内存开支,还有减少系统原创 2022-09-04 13:38:32 · 1013 阅读 · 0 评论 -
Go 学习笔记(89) — 接口类型变量的等值比较操作(nil 接口变量、空接口类型变量、非空接口类型变量)
nil 接口变量、空接口类型变量、非空接口类型变量、空接口类型与非空接口类型之间的比较原创 2022-09-03 23:01:29 · 817 阅读 · 0 评论 -
Go 学习笔记(88) — 字符串拼接方法和性能、字符串组成、UTF-8 编码方案、字符串之间转换
字符串多种拼接方法和性能比对、字符串组成、UTF-8 编码方案、字符串之间转换原创 2022-09-03 22:41:22 · 796 阅读 · 0 评论 -
Go 学习笔记(87) — 函数式选项,初始化结构体对象可变参数
初始化结构体对象时用到的可变参数package newdemotype Foo struct { name string id int age int db interface{}}func NewFoo(name string, id int, age int, db interface{}) *Foo { return &Foo{ name: name, id: id,原创 2022-09-02 22:19:56 · 539 阅读 · 0 评论 -
Go 学习笔记(86)— Go 方法接受者参数类型选择
Go 方法接受者参数类型选择原创 2022-08-29 23:11:28 · 1381 阅读 · 0 评论 -
Go 学习笔记(85)— 常见错误汇总(数组值传递、map遍历顺序不固定、返回值被屏蔽、recover 必须在 defer 函数、goroutine 锁死、闭包错误引用同一个变量)
数组是值传递,在函数调⽤参数中,数组是值传递,⽆法通过修改数组类型的参数返回结 果func main() { x := [3]int{1, 2, 3}func(arr [3]int) { arr[0] = 7 fmt.Println(arr) }(x) fmt.Println(x) }必要时需要使⽤切⽚。map遍历是顺序不固定,map是⼀种hash表实现,每次遍历的顺序都可能不⼀样func main() { m := map[string]string{ "1": "1", "2": "2",原创 2022-08-28 22:08:37 · 524 阅读 · 0 评论 -
Go 学习笔记(84)— Go 项目目录结构(开发目录、测试目录、部署目录、项目管理目录 makefile、scripts、build、tools、文档目录、makefile规则)
Go 项目目录结构、Makefile 结构、编译命令原创 2022-03-02 17:21:50 · 21279 阅读 · 4 评论 -
Go 学习笔记(83)— 编码规范及常用开发技巧
1. 规范指南1.1 包名package 的命名应该遵循如下原则:只由小写字母组成。不包含大写字母和下划线等字符;简短并包含一定的上下文信息。例如 time、list、http 等;不能是含义模糊的常用名,或者与标准库同名。例如不能使用 util 或者 strings;包名能够作为路径的 base name,如果包名字符串过长则尽量使用目录来分割。例如应该使用encoding/base64而不是 encoding_base64或者 encodingbase64;包名与目录保持一致,尽量有意义原创 2022-02-09 21:45:00 · 1136 阅读 · 0 评论 -
Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件)
1. viper 特点viper 是一个完整的 Go应用程序的配置解决方案,它被设计为在应用程序中工作,并能处理所有类型的配置需求和格式。支持特性功能如下:设置默认值读取 JSON、TOML、YAML、HCL、envfile和 Java属性的配置文件监控配置文件改动,并热加载配置文件从环境变量中读取从远程配置中心读取配置(etcd/consul),并监控变动从命令行标志中读取从缓冲区读取支持直接设置配置项的值viper读取配置文件的优先级顺序:viper.Set() 所设置的值原创 2021-12-07 22:30:00 · 3273 阅读 · 1 评论 -
Go 学习笔记(81)— Go 性能分析工具 pprof
Go 语言工具链中的 go pprof 可以帮助开发者快速分析及定位各种性能问题,如 CPU消耗 、内存分配及阻塞分析 。性能分析首先需要使用 runtime.pprof 包嵌入到待分析程序的入口和结束处 。runtime.pprof 包在运行时对程序进行每秒 100 次的采样,最少采样 1 秒。然后将生成的数据输出 , 让开发者写入文件或者其他媒介上进行分析。go pprof 工具链配合 Graphviz 图形化工具可以将 runtime.pprof 包生成的数据转换为 PDF格式,以图片的原创 2021-10-15 20:11:42 · 1531 阅读 · 0 评论 -
Go 学习笔记(80)— Go 标准库 container/list(单链表、双链表)
列表是一种非连续存储的容器,由多个节点组成,节点通过一些变量记录彼此之间的关系。列表有多种实现方法,如单链表、双链表等。在 Go 语言中,将列表使用 container/list 包来实现,内部的实现原理是双链表。列表能够高效地进行任意位置的元素插入和删除操作。1. 列表初始化list 的初始化有两种方法: New 和声明。两种方法的初始化效果都是一致的。1.1 通过 New方法初始化 list变量名 :=list.New()1.2 通过声明初始化 listvar 变量名 list.Li原创 2021-09-27 20:28:34 · 897 阅读 · 0 评论 -
Go 学习笔记(79)— Go 标准库 net(获取本机IP地址)
1. 获取本机 IP 地址package mainimport ( "fmt" "net")// 获取本机网卡IPfunc getLocalIP() (ipv4 string, err error) { // var ( // addrs []net.Addr // addr net.Addr // ipNet *net.IPNet // IP地址 // isIpNet bool // ) // 获取所有网卡 addrs, err := net.InterfaceA原创 2021-04-22 22:17:48 · 2426 阅读 · 2 评论 -
Go 学习笔记(78)— Go 标准库 net/http 创建服务端(接收 GET、POST 请求)
使用 net/http 标准库创建一个 http 的 restful api 的服务端,用来处理 GET、POST 等请求。源代码如下:package mainimport ( "encoding/json" "fmt" "net" "net/http" "strconv" "time")type Contact struct { Home string `json:"home"` Cell string `json:"cell"`}type Student struct原创 2021-04-21 22:21:21 · 604 阅读 · 0 评论 -
Go 学习笔记(77)— Go 第三方库之 cronexpr(解析 crontab 表达式,定时任务)
cronexpr 支持的比 Linux 自身的 crontab 更详细,精确到秒级别。1. 解析 crontab 表达式package mainimport ( "fmt" "time" "github.com/gorhill/cronexpr")func doTask() { fmt.Println("I am running")}func main() { // 每隔 5 秒执行1次 expr, err := cronexpr.Parse("*/5 * * * * *原创 2021-04-20 22:28:22 · 3075 阅读 · 0 评论 -
Go 学习笔记(76)— Go 标准库 net/http 创建客户端(发送 GET、POST 请求)
1. Get 请求1.1 使用 net/http 包的快捷方法 GETpackage mainimport ( "fmt" "io/ioutil" "net/http")func main() { resp, err := http.Get("http://www.baidu.com") if err != nil { fmt.Println(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp原创 2021-03-22 22:18:23 · 2069 阅读 · 0 评论 -
Go 学习笔记(75)— 栈内存、堆内存、逃逸分析
为了让程序员更好地专注于业务代码的实现,Go 语言增加了垃圾回收机制,自动地回收不再使用的内存。Go 语言有两部分内存空间:栈内存和堆内存。1. 栈内存和堆内存栈内存由编译器自动分配和释放,开发者无法控制。栈内存一般存储函数中的局部变量、参数等,函数创建的时候,这些内存会被自动创建;函数返回的时候,这些内存会被自动释放。堆内存的生命周期比栈内存要长,如果函数返回的值还会在其他地方使用,那么这个值就会被编译器自动分配到堆上。堆内存相比栈内存来说,不能自动被编译器释放,只能通过垃圾回收器才能释放,所以栈内原创 2021-02-28 19:53:27 · 2372 阅读 · 0 评论 -
Go 学习笔记(74)— Go 标准库之 unsafe
Go 语言自带的 unsafe 包的高级用法, 顾名思义,unsafe 是不安全的。Go 将其定义为这个包名,也是为了让我们尽可能地不使用它。不过虽然不安全,它也有优势,那就是可以绕过 Go 的内存安全机制,直接对内存进行读写。所以有时候出于性能需要,还是会冒险使用它来对内存进行操作。1. 指针类型转换Go 是一门强类型的静态语言。强类型意味着一旦定义了,类型就不能改变;静态意味着类型检查在运行前就做了。同时出于安全考虑,Go 语言是不允许两个指针类型进行转换的。我们一般使用 *T 作为一个指针类型,原创 2021-02-27 19:42:26 · 413 阅读 · 0 评论 -
Go 学习笔记(73)— Go 静态代码分析工具 golangci-lint
golangci-lint 的使用原创 2021-02-14 23:49:34 · 16935 阅读 · 5 评论 -
Go 学习笔记(72)— Go 第三方库之 pkg/errors 带堆栈的错误处理
包 github.com/pkg/errors 让开发人员很容易在 error 错误信息上带上堆栈信息,可以更快更准确定位错误,例如行号等信息。如果项目代码比较复杂,且经常需要追踪 Bug,建议使用github.com/pkg/errors 这个错误处理包。安装go get -v github.com/pkg/errors这个包和标准库的 errors 包重名,并且都有 New() 函数,因此从标准库的错误处理方式转为带堆栈的错误处理上来还是比较方便的。下面代码使用 errors.Wr原创 2021-02-12 16:42:37 · 5789 阅读 · 2 评论 -
Go 学习笔记(71)— Go 接口 interface (接口定义、接口实现、接口调用、值接收者、指针接收者)
1. 接口的定义接口是和调用方的一种约定,它是一个高度抽象的类型,不用和具体的实现细节绑定在一起。接口要做的是定义好约定,告诉调用方自己可以做什么,但不用知道它的内部实现,这和我们见到的具体的类型如 int、map、slice 等不一样。接口的定义和结构体稍微有些差别,虽然都以 type 关键字开始,但接口的关键字是 interface,表示自定义的类型是一个接口。也就是说 person 是一个接口,它有两个方法 sayName() string 和 sayAge() int,整体如下面的代码所示:原创 2021-01-10 22:58:42 · 5566 阅读 · 1 评论 -
Go 学习笔记(70)— Go 变量声明、变量初始化、值类型变量赋值、指针类型变量赋值
1. 变量声明要单纯声明一个变量,可以通过 var 关键字,如下所示:var s string该示例只是声明了一个变量 s,类型为 string,并没有对它进行初始化,所以它的值为 string 的零值,也就是 “”(空字符串)。来声明一个指针类型的变量试试,如下所示:var sp *string发现也是可以的,但是它同样没有被初始化,所以它的值是 *string 类型的零值,也就是 nil。2. 变量初始化变量可以通过 = 运算符赋值,也就是修改变量的值。如果在声明一个变量的时候就给这原创 2021-01-08 23:07:24 · 972 阅读 · 0 评论 -
Go 学习笔记(69)— Go Modules 使用详解(设置GO111MODULE、设置代理、初始化项目、创建依赖项、回退依赖项版本、删除未使用的依赖项)
采用 Go Module 的方式,可以在任何位置创建你的 Go 语言项目。假设你的项目位置是 /home/wohu/demo,打开终端,输入如下命令切换到该目录下:$ cd /home/wohu/demo然后再执行如下命令创建一个 Go Module 项目:$ go mod init go_demo执行成功后,会生成一个 go.mod 文件。然后在当前目录下创建一个 main.go 文件,这样整个项目目录结构是:wohu@wohu:~/demo$ tree.├── go.mod├──原创 2020-12-02 22:56:32 · 20656 阅读 · 4 评论 -
Go 学习笔记(68)— goroutine 并发控制神器 Context
1. 什么是 Context一个任务会有很多个 goroutine 协作完成,一次 HTTP 请求也会触发很多个 goroutine 的启动,而这些 goroutine 有可能会启动更多的子 goroutine ,并且无法预知有多少层 goroutine 、每一层有多少个 goroutine 。如果因为某些原因导致任务终止了,HTTP 请求取消了,那么它们启动的 goroutine 怎么办?该如何取消呢?因为取消这些 goroutine 可以节约内存,提升性能,同时避免不可预料的 Bug。Contex原创 2020-12-02 22:04:54 · 876 阅读 · 2 评论 -
Go 学习笔记(67)— Go 并发安全字典 sync.Map
1. 并发不安全的 mapGo 语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。换句话说,在同一时间段内,让不同 goroutine 中的代码,对同一个字典进行读写操作是不安全的。字典值本身可能会因这些操作而产生混乱,相关的程序也可能会因此发生不可预知的问题。package mainimport ( "fmt" "time")func main() { m := map[int]string{ 1: "haha", } go read(m) ti原创 2020-12-01 22:56:50 · 832 阅读 · 0 评论 -
Go 学习笔记(66)— Go 并发同步原语(sync.Mutex、sync.RWMutex、sync.Once)及并发模型(ping-pong 模式、fan-in 模式、fan-out 模式)
1. 竞态条件一旦数据被多个线程共享,那么就很可能会产生争用和冲突的情况。这种情况也被称为竞态条件(race condition),这往往会破坏共享数据的一致性。举个例子,同时有多个线程连续向同一个缓冲区写入数据块,如果没有一个机制去协调这些线程的写入操作的话,那么被写入的数据块就很可能会出现错乱。比如,在线程 A 还没有写完一个数据块的时候,线程 B 就开始写入另外一个数据块了。显然,这两个数据块中的数据会被混在一起,并且已经很难分清了。因此,在这种情况下,我们就需要采取一些措施来协调它们对缓冲区原创 2020-11-28 14:15:37 · 1073 阅读 · 1 评论 -
Go 学习笔记(65)— Go 中函数参数是传值(函数参数为数组、切片、map、chan、struct 等)
package mainimport "fmt"func main() { // 示例1。 array1 := [3]string{"a", "b", "c"} fmt.Printf("The array: %v\n", array1) array2 := modifyArray(array1) fmt.Printf("The modified array: %v\n", array2) fmt.Printf("The original array: %v\n", array1) f.原创 2020-11-19 22:07:18 · 3408 阅读 · 4 评论 -
Go 学习笔记(64)— Go error.New 创建接口错误对象、fmt.Errorf 创建接口错误对象、errors.Is 和 errors.As
1. error 接口定义除用 panic 引发中断性错误外,还可返回 error 类型错误对象来表示函数调用状态。 error 接口定义是:type error interface { Error() string}在这个接口类型的声明中只包含了一个方法 Error 。Error 方法不接受任何参数,但是会返回一个 string 类型的结果。它的作用是返回错误信息的字符串表示形式。一般情况下在 Go 里只使用 error 类型判断错误, Go 官方希望开发者能够很清楚的掌控所有的异常,原创 2020-11-17 22:20:50 · 12487 阅读 · 0 评论 -
Go 学习笔记(63)— Go 中的 for ... range 对切片和数组的差异
1. 迭代对象是切片,迭代过程中修改切片package mainimport "fmt"func main() { // 示例1。 numbers1 := []int{1, 2, 3, 4, 5, 6} // 只有一个迭代变量时,i 表示为迭代对应元素的索引值 for i := range numbers1 { if i == 3 { numbers1[i] |= i } } fmt.Println(numbers1) // [1 2 3 7 5 6] fmt.Prin原创 2020-11-16 22:05:55 · 347 阅读 · 0 评论 -
Go 学习笔记(62)— Go 中 switch 语句中的 switch 表达式和 case 表达式之间的关系
switch 语句对 switch 表达式的结果类型,以及各个 case 表达式中子表达式的结果类型都是有要求的。毕竟,在 Go 语言中,只有类型相同的值之间才有可能被允许进行判等操作。1. switch 类型和 case 类型不匹配1.1 switch 类型和 case 类型不能转换场景package mainimport "fmt"func main() { value1 := [...]int8{0, 1, 2, 3, 4, 5, 6} switch 1 + 3 { // 这条语原创 2020-11-15 21:43:17 · 1556 阅读 · 0 评论 -
Go 学习笔记(61)— Go 高阶函数、函数作为一等公民(函数作为输入参数、返回值、变量)的写法
先来说说什么是高阶函数?简单地说,高阶函数可以满足下面的两个条件之一:接受其他的函数作为参数把其他的函数作为结果返回只要满足了其中任意一个特点,我们就可以说这个函数是一个高阶函数。高阶函数也是函数式编程中的重要概念和特征。高阶函数和闭包所谓闭包就是一个函数体内部引用了一个外部的变量高阶函数和函数式编程的特点就是 支持函数作为参数或者返回值示例:package mainimport ( "errors" "fmt")type operate func(x, y int)原创 2020-11-14 22:13:45 · 1225 阅读 · 1 评论 -
Go 学习笔记(60)— Go 第三方库之 go-redis(初始化 redis、操作 string、操作 list、操作 set、操作 hset)
1. 第三方库 go-redis因为 Go 标准库中是没提供 redis 的库,所以我们选择用 go-redis 这个第三方库。源码地址为 https://github.com/go-redis/redis 在命令行中使用 go get 来安装go get github.com/go-redis/redis2. 初始化 Redis在进行代码之前,需要先安装 redis,安装指导请参考:https://blog.youkuaiyun.com/wohu1104/article/details/867555原创 2020-09-19 23:08:49 · 4887 阅读 · 0 评论 -
Go 学习笔记(59)— Go 第三方库之 etcd/clientv3 封装为方法使用(建立连接、设置key-value、获取key-value、获取带前缀的key-value)
1. 示例 1package mainimport ( "context" "fmt" "go.etcd.io/etcd/clientv3" "time")// 写入读取func SetGet() { // 配置 etcd ,创建客户端 cli, err := clientv3.New(clientv3.Config{ Endpoints: []string{"127.0.0.1:2379"}, DialTimeo原创 2020-09-18 22:12:05 · 1528 阅读 · 0 评论 -
Go 学习笔记(58)— Go 第三方库之 etcd/clientv3(连接客户端、PUT、GET、Lease、Op、Txn、Watch 基础概念说明)
1. 安装 Golang 的 Etcd 包我们使用 v3 版本的 etcd client , 首先通过 go get 下载并编译安装 etcd clinet v3。go get -v github.com/coreos/etcd/clientv3该命令会将包下载到 $GOPATH/src/github.com/coreos/etcd/clientv3 中,所有相关依赖包会自动下载编译,包括protobuf、grpc等。我们主要梳理一下使用 etcd 时经常用到的主要 API 并进行演示。2. 连原创 2020-09-15 22:31:08 · 11714 阅读 · 3 评论 -
Go 学习笔记(57)— Go 第三方库之 amqp (RabbitMQ 生产者、消费者整个流程)
1. 安装 rabbitmq 的 golang 包golang 可使用库 github.com/streadway/amqp 操作 rabbitmq 。使用下面命令安装 RabbitMQ 。go get -v github.com/streadway/amqp2. 生产者流程在 Golang 中创建 rabbitmq 生产者基本步骤是:连接 Connection创建 Channel创建或连接一个交换器创建或连接一个队列交换器绑定队列投递消息关闭 Channel关闭 Connec原创 2020-09-14 22:31:29 · 5820 阅读 · 0 评论 -
Go 学习笔记(56)— Go 第三方库 sqlx (操作数据库)
1. 安装数据库在 Go 标准库中是没有数据库驱动,只提供了驱动接口,有很多第三方实现了驱动,以下两种选择我们都可以进行操作,在本文中选择 sqlx 。第三方库 MySQL 驱动库: go-sql-driver/mysql第三方库 sqlx 数据库操作: jmoiron/sqlx进入 $GOPATH 目录使用 go get 下载, 打开命令行执行以下命令:go get github.com/go-sql-driver/mysqlgo get github.com/jmoiron/sql原创 2020-09-13 19:27:37 · 1466 阅读 · 0 评论 -
Go 学习笔记(55)— Go 标准库 sql (初始化数据库、插入、更新、删除数据库表、单行查询、多行查询、事务处理)
1. 标准库说明Go 的标准库中是没有数据库驱动,只提供了驱动接口,有很多第三方实现了驱动,我们这里选择 go-sql-driver 这个实现是目前使用最多的。github 地址是:https://github.com/go-sql-driver/mysqlGo 标准库中的 SQL 安装包是在 $GOROOT/src/database/sql/ 目录下,如下图所示:ubuntu@ubuntu:~$ ls /usr/local/go/src/database/sql/convert.go原创 2020-09-12 21:50:19 · 2426 阅读 · 2 评论 -
Go 学习笔记(54)— Go 第三方库之 uber-go/zap/lumberjack(记录日志到文件、支持自动分割日志、支持日志级别、打印调用文件、函数和行号)
1. 简要说明zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割,这里我们可以使用 lumberjack 也是 zap 官方推荐用于日志分割,结合这两个库我们就可以实现以下功能的日志机制:能够将事件记录到文件中,而不是应用程序控制台;日志切割能够根据文件大小、时间或间隔等来切割日志文件;支持不同的日志级别,例如 DEBUG , INFO , WARN , ERROR 等;能够打印基本信息,如调用文件、函数名和行号,日志时间等;原创 2020-07-13 22:35:09 · 11298 阅读 · 1 评论 -
Go 学习笔记(53)— Go 标准库之 path(判断绝对路径、拆分目录和文件、组合路径、返回路径目录、获取路径最后文件名、获取文件扩展名、路径匹配规则)
1. 概述说明import "path"path 实现了对斜杠分隔的路径的实用操作函数。2. 主要函数2.1 func IsAbsfunc IsAbs(path string) boolIsAbs 返回路径是否是一个绝对路径。2.2 func Splitfunc Split(path string) (dir, file string)Split 函数将路径从最后一个斜杠后面位置分隔为两个部分( dir 和 file )并返回。如果路径中没有斜杠,函数返回值 dir 会设为空字符串原创 2020-06-13 23:23:34 · 5427 阅读 · 0 评论 -
Go 学习笔记(52)— Go 标准库之 path/filepath(判断绝对路径、拆分目录和文件、组合路径、返回路径目录、获取路径最后文件名、获取文件扩展名、路径匹配规则、递归遍历目录)
1. 概述说明import "path/filepath"filepath 包实现了兼容各操作系统的文件路径的实用操作函数。2. 主要函数2.1 func IsAbsfunc IsAbs(path string) boolIsAbs 返回路径是否是一个绝对路径。2.2 func Absfunc Abs(path string) (string, error)Abs 函数返回 path 代表的绝对路径,如果 path 不是绝对路径,会加入当前工作目录以使之成为绝对路径。因为硬链接的存在原创 2020-06-12 22:25:44 · 4871 阅读 · 0 评论 -
Go 学习笔记(51)— Go 标准库之 strings(字符串比较、字符串前后缀、字符串统计、字符串索引、字符串包含、字符串转换、字符串复制、字符串替换、字符串去除、字符串分割和连接)
1. 概述说明import "strings"strings 包实现了用于操作字符的简单函数。 strings 包与 bytes 包中的函数用法基本一样。2. 主要函数2.1 字符串比较func Compare(a, b string) int // 如果a==b返回0;如果a<b返回-1;否则返回+1func EqualFold(s, t string) bool // 判断两个utf-8编码字符串(将unicode大写、小写、标题三种格式字符视为相同)是否相同。2.2 字符串原创 2020-06-11 21:19:58 · 692 阅读 · 0 评论