【声明】

非完全原创,部分内容来自于学习其他人的理论和B站视频。如果有侵权,请联系我,可以立即删除掉。

一、单元测试

为什么需要单元测试
(1)如果按照传统的测试方法,则需要在main函数种添加测试项,如果项目正在运行,则需要停止项目
(2)如果需要测试多个函数或者模块,则需要全部写在main函数中,不利于项目的管理
(3)go语言自带单元测试框架,可以解决上述问题

下面转载自:https://www.cnblogs.com/zongmin/p/16365976.html
在go语言中,一般使用go test命令进行函数测试,包目录下所有以_test.go为后缀的文件都是go test测试的一部分,不会被go build编译到最终的可执行文件_test.go中的测试函数主要分为3种:

类型 格式 作用
测试函数 函数名前缀为Test 测试程序的一些逻辑行为是否正确
基准函数 函数名前缀为Benchmark 测试函数的性能
示例函数 函数名前缀为Example 为文档提供示例文档

1、相关测试方法

1.1、单元测试的函数

func (c *T) Error(args ...interface{})
func (c *T) Errorf(format string, args ...interface{})func (c *T) Fatal(args ...interface{})
func (c *T) Fatalf(format string, args ...interface{})func (c *T) Log(args ...interface{})
func (c *T) Logf(format string, args ...interface{})func (t *T) Parallel()
//Parallel 用于表示当前测试只会与其他带有 Parallel 方法的测试并行进行测试。func (t *T) Run(name string, f func(t *T)) bool
//执行名字为 name 的子测试 f ,并报告 f 在执行过程中是否出现了任何失败。Run 将一直阻塞直到 f 的所有并行测试执行完毕func (c *T) Skip(args ...interface{})
//将当前测试标识为“被跳过”并停止执行该测试

1.2、t.Skip() 方法

// 为了节省时间支持在单元测试时跳过某些耗时的测试用例
func TestTimeConsuming(t *testing.T) {if testing.Short() {t.Skip("short模式下会跳过该测试用例")}...
}

当执行go test -short时就不会执行上面的TestTimeConsuming测试用例。

2、测试示例

2.1、基本使用

2.1.1、测试的文件

(1)待测试函数的文件

//cal.go
package cal
func add(n int) int {return (n + 1) * n / 2
}
func multi(n uint64) uint64 {if n == 1 {return 1}return n * multi(n-1)
}
func fiber(n int) int {if n == 1 || n == 2 {return 1}return fiber(n-1) + fiber(n-2)
}

(2)测试函数文件1

//cal_test.go
package cal
import ("testing"
)
func TestAdd(t *testing.T) {res := add(10)if res != 55 {t.Fatalf("TestAdd执行失败, 期望值=55, 实际值=%d\n", res)}t.Logf("TestAdd执行成功")
}
func TestMultiAll(t *testing.T) {tests := []struct {name         stringpara, expect uint64}{{"n = 3", 3, 6},{"n = 4", 4, 24},{"n = 5", 5, 120},{"n = 7", 7, 5040},{"n = 10", 10, 3628801},}for _, v := range tests {t.Run(v.name, func(tt *testing.T) {real := multi(v.para)if v.expect != real {t.Errorf("[%#v] expect = %v, but output = %v\n", v.name, v.expect, real)}})}
}

(3)测试函数文件2

//fiber_test.go
package cal
import ("strconv""testing"
)
func TestFiber(t *testing.T) {tests := map[int]int{1: 1, 2: 1, 3: 2, 4: 3, 5: 5, 6: 8}for key, val := range tests {t.Run("fiber_"+strconv.Itoa(key), func(tt *testing.T) {real := fiber(key)if val != real {t.Errorf("[%#v] expect = %v, but output = %v\n", "fiber_"+strconv.Itoa(key), val, real)}})}
}

2.1.2、测试方法

(1)直接测试所有文件

UnitTest\add_sub> go test -v
=== RUN   TestAddcal_test.go:12: TestAdd执行成功
--- PASS: TestAdd (0.00s)
=== RUN   TestMultiAll
=== RUN   TestMultiAll/n_=_3
=== RUN   TestMultiAll/n_=_4
=== RUN   TestMultiAll/n_=_5
=== RUN   TestMultiAll/n_=_7
=== RUN   TestMultiAll/n_=_10
=== CONT  TestMultiAllcal_test.go:30: ["n = 10"] expect = 3628801, but output = 3628800
--- FAIL: TestMultiAll (0.00s)--- PASS: TestMultiAll/n_=_3 (0.00s)--- PASS: TestMultiAll/n_=_4 (0.00s)--- PASS: TestMultiAll/n_=_5 (0.00s)--- PASS: TestMultiAll/n_=_7 (0.00s)--- PASS: TestMultiAll/n_=_10 (0.00s)
=== RUN   TestFiber
=== RUN   TestFiber/fiber_4
=== RUN   TestFiber/fiber_5
=== RUN   TestFiber/fiber_6
=== RUN   TestFiber/fiber_1
=== RUN   TestFiber/fiber_2
=== RUN   TestFiber/fiber_3
--- PASS: TestFiber (0.00s)--- PASS: TestFiber/fiber_4 (0.00s)--- PASS: TestFiber/fiber_5 (0.00s)--- PASS: TestFiber/fiber_6 (0.00s)--- PASS: TestFiber/fiber_1 (0.00s)--- PASS: TestFiber/fiber_2 (0.00s)--- PASS: TestFiber/fiber_3 (0.00s)
FAIL
exit status 1
FAIL    Test0/UnitTest/add_sub  0.182s

(2)只显示失败项

UnitTest\add_sub> go test
--- FAIL: TestMultiAll (0.00s)cal_test.go:30: ["n = 10"] expect = 3628801, but output = 3628800
FAIL
exit status 1
FAIL    Test0/UnitTest/add_sub  0.179s

(3)测试单个文件

UnitTest\add_sub> go test -v fiber_test.go cal.go
=== RUN   TestFiber
=== RUN   TestFiber/fiber_3
=== RUN   TestFiber/fiber_4
=== RUN   TestFiber/fiber_5
=== RUN   TestFiber/fiber_6
=== RUN   TestFiber/fiber_1
=== RUN   TestFiber/fiber_2
--- PASS: TestFiber (0.00s)--- PASS: TestFiber/fiber_3 (0.00s)--- PASS: TestFiber/fiber_4 (0.00s)--- PASS: TestFiber/fiber_5 (0.00s)--- PASS: TestFiber/fiber_6 (0.00s)--- PASS: TestFiber/fiber_1 (0.00s)--- PASS: TestFiber/fiber_2 (0.00s)
PASS
ok      command-line-arguments  0.179s

2.2、多个同参同返回值类型函数的测试

2.2.1、测试文件

//joinStr.go
package joinStrfunc joinStr_fmtSprint(str []string) string {return fmt.Sprint(str)
}func joinStr_bytesBuffer(str []string) string {var buf bytes.Bufferfor _, val := range str {buf.WriteString(val)}return buf.String()
}func joinStr_stringsBuilder(str []string) string {var builder strings.Builderfor _, val := range str {builder.WriteString(val)}return builder.String()
}func joinStr_strAdd(str []string) string {var s string = str[0]for i := 1; i < len(str); i++ {s += str[i]}return s
}func jonStr_stringsJoin(str []string) string {return strings.Join(str, "")
}func joinStr_byteAppend(str []string) string {var sli []bytefor _, val := range str {sli = append(sli, []byte(val)...)}return string(sli)
}
//joinStr_test.go
package joinStrimport ("fmt""testing"
)func TestAll(t *testing.T) {append_cnt := 10var f [6]func([]string) stringf[0] = joinStr_fmtSprintf[1] = joinStr_bytesBufferf[2] = joinStr_stringsBuilderf[3] = joinStr_strAddf[4] = jonStr_stringsJoinf[5] = joinStr_byteAppendexpect := `Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.Gopher image by Renee French, licensed under Creative Commons 3.0 Attributions license.Our canonical Git repository is located at https://go.googlesource.com/go. There is a mirror of the repository at https://github.com/golang/go.Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file.Download and Install Binary Distributions Official binary distributions are available at https://go.dev/dl/.After downloading a binary release, visit https://go.dev/doc/install for installation instructions.Install From Source If a binary distribution is not available for your combination of operating system and architecture, visit https://go.dev/doc/install/source for source installation instructions.Contributing Go is the work of thousands of contributors. We appreciate your help!To contribute, please read the contribution guidelines at https://go.dev/doc/contribute.Note that the Go project uses the issue tracker for bug reports and proposals only. See https://go.dev/wiki/Questions for a list of places to ask questions about the Go language.`var str_app []stringstr_app = append(str_app, expect)for i := 0; i < append_cnt; i++ {str_app = append(str_app, str_app...)}expect = fmt.Sprint(str_app)bytes := []byte(expect)var str []stringfor _, v := range bytes {str = append(str, string(v))}test := []struct {name stringfuc  func([]string) string}{//{"fmt.Sprintf", f[0]},{"bytes.Buffer", f[1]},{"strings.Builder", f[2]},{"string and +", f[3]},{"strings.Join", f[4]},{"byte and append", f[5]},}for _, tc := range test {tc := tct.Run(tc.name, func(t *testing.T) {t.Parallel()rel := tc.fuc(str)if expect != rel {t.Errorf("[%#v] expect not equal but output", tc.name)}})}
}

2.2.2、测试结果

//append_cnt := 10
UintTest\joinStr> go test -v
=== RUN   TestAll
=== RUN   TestAll/bytes.Buffer
=== PAUSE TestAll/bytes.Buffer
=== RUN   TestAll/strings.Builder
=== PAUSE TestAll/strings.Builder
=== PAUSE TestAll/strings.Join
=== RUN   TestAll/byte_and_append
=== PAUSE TestAll/byte_and_append
=== CONT  TestAll/bytes.Buffer
=== CONT  TestAll/strings.Join
=== CONT  TestAll/strings.Builder
--- PASS: TestAll (0.11s)--- PASS: TestAll/bytes.Buffer (0.01s)--- PASS: TestAll/strings.Builder (0.01s)--- PASS: TestAll/byte_and_append (0.02s)--- PASS: TestAll/strings.Join (0.02s)--- PASS: TestAll/string_and_+ (117.89s)
PASS
ok      Test0/UintTest  118.200s
//append_cnt := 14
UnitTest\joinStr> go test -v
=== RUN   TestAll
=== RUN   TestAll/bytes.Buffer
=== PAUSE TestAll/bytes.Buffer
=== RUN   TestAll/strings.Builder
=== PAUSE TestAll/strings.Builder
=== RUN   TestAll/strings.Join
=== PAUSE TestAll/strings.Join
=== RUN   TestAll/byte_and_append
=== PAUSE TestAll/byte_and_append
=== CONT  TestAll/bytes.Buffer
=== CONT  TestAll/strings.Join
=== CONT  TestAll/strings.Builder
=== CONT  TestAll/byte_and_append
--- PASS: TestAll (1.33s)--- PASS: TestAll/strings.Builder (0.14s)--- PASS: TestAll/bytes.Buffer (0.20s)--- PASS: TestAll/strings.Join (0.23s)--- PASS: TestAll/byte_and_append (0.24s)
PASS
ok      Test0/UnitTest/joinStr  1.873s

由上面的结果分析(不包括fmt.Sprintf
字符串拼接时,速度由快到慢依次是:
strings.Builder > bytes.Buffer > strings.Join > append([]string, []byte(str)) > str1 + str2

二、Redis

1、Redis的安装和使用

Linux版本:https://redis.io/download/
Windows版本:https://github.com/MicrosoftArchive/redis/releases
如果下载的是安装包msi,则需要安装到系统,可以选择自动配置环境变量;如果下载的是压缩包,则解压后打开。
安装完成之后,运行服务端(如windows版本的是redis-server.exe)对端口6379进行持续监听。注意:Redis客户端操作数据库的过程中需要保持服务端一直在运行

打开客户端即可对数据库进行操作,比如添加、查看、删除字符串:

2、Redis的5大数据类型

Redis的5大数据类型的操作方法网址:http://redisdoc.com/
五大数据类型为:String(字符串)、Hash(哈希表)、List(列表)、Set(集合)、zset(sorted set, 有序集合)

2.1、String(字符串)

字符串是redis最基本的数据类型,一个key对应这一个value。它是二进制安全的,可以存放图片、视频等数据,一个value最大是512M

主要方法

  • set key value。 将字符串值 value 关联到 key ;如果 key 已经持有其他值, SET 就覆写旧值, 无视类型;当 SET 命令对一个带有生存时间(TTL)的键进行设置之后, 该键原有的 TTL 将被清除。
  • setex key time_s value。设置 key 的有效时间为time_s 秒钟,超过这个时间后,value 值会被清空
  • mset key1 value1 key2 value2 ...。一次性设置多个字符串
  • get key。获取 key 所对应的 value 值
  • mget key1 key2 ...。一次性获取多个 key 的 value
  • del key1 key2 ...。删除1个或多个 key
127.0.0.1:6379> setex name 5 go
OK
127.0.0.1:6379> get name
"go"
127.0.0.1:6379> get name
(nil)127.0.0.1:6379> set addr1 hubei
OK
127.0.0.1:6379> mset addr2 beijing addr3 hainan
OK
127.0.0.1:6379> mget addr1 addr2 addr3
1) "hubei"
2) "beijing"
3) "hainan"127.0.0.1:6379> del addr2
(integer) 1
127.0.0.1:6379> get add2
(nil)
127.0.0.1:6379> del addr1 addr3
(integer) 2
127.0.0.1:6379> get add3
(nil)
127.0.0.1:6379> get add1
(nil)

2.2、Hash(哈希表)

在redis中,哈希表是多个键值对的集合,且键和值都是string类型。这种组合的方式非常适合存储对象

主要方法

  • hset key field value。将哈希表 key 中域 field 的值设置为 value ;如果哈希表并不存在, 则创建哈希表将并执行 HSET 操作,如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。
  • hmset key field value [field value …]。同时将多个 field-value (域-值)对设置到哈希表 key 中。此命令会覆盖哈希表中已存在的域。
  • hget hash field。返回哈希表中给定域的值。
  • hmget key field [field …]。返回哈希表 key 中,一个或多个给定域的值。如果给定的域不存在于哈希表,那么返回一个 nil 值
  • hgetall key。返回哈希表 key 中,所有的域和值
  • hdel key field [field …]。删除哈希表 key 中一个或多个域,不存在的域将被忽略。返回值表示成功删除的域的个数
  • hexists key field。判断域 field 在哈希表 key 中是否存在
127.0.0.1:6379> hmset person1 sex man age 30 addr wuhan mail zs@qq.com
OK127.0.0.1:6379> hget person1 addr
"wuhan"
127.0.0.1:6379> hmget person1 name mail sex
1) "ZhangSan"
2) "zs@qq.com"
3) "man"
127.0.0.1:6379> hgetall person11) "name"2) "ZhangSan"3) "sex"4) "man"5) "age"6) "30"7) "addr"8) "wuhan"9) "mail"
10) "zs@qq.com"127.0.0.1:6379> hdel person1 sex addr age
(integer) 3
127.0.0.1:6379> hgetall person1
1) "name"
2) "ZhangSan"
3) "mail"
4) "zs@qq.com"
127.0.0.1:6379> hexists person1 name
(integer) 1
127.0.0.1:6379> hexists person1 sex
(integer) 0

2.3、List(列表)

列表是简单的字符串列表(数据可以重复),按照插入的顺序进行排序,插入和删除都可以指定头部(左边)还是尾部(右边)。redis中的列表本质上是链表:当元素个数不超过512,且每个元素均小于64 bytes时,用ziplist存储;其他情况用双向链表来存储。因此,redis列表的插入和删除会很快,索引定位会很慢

主要方法

  • lpush key value [value …]。将一个或多个值 value 插入到列表 key 的表头(左边);如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头,返回列表中的元素个数。如对空列表 mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a
  • rpush key value [value …]。将一个或多个值 value 插入到列表 key 的表尾(右边)
  • lpop key。移除并返回列表 key 的头部元素
  • rpop key。移除并返回列表 key 的尾部元素
  • lrange key start stop。返回列表 key 中指定区间内的元素,区间以偏移量 start 和 stop 指定。以 0 表示列表的第一个元素,以 1 表示列表的最后一个元素
  • llen key。返回列表 key 的长度。如果 key 不存在,则 key 被解释为一个空列表,返回 0。如果 key 不是列表类型,返回一个错误
127.0.0.1:6379> lpush city hubei shanghai
(integer) 2  //city: (head)shanghai hubei(tail)
127.0.0.1:6379> rpush city beijing hunan
(integer) 4  //city: (head)shanghai hubei beijing hunan(tail)
127.0.0.1:6379> lrange city 0 -1
1) "shanghai"
2) "hubei"
3) "beijing"
4) "hunan"
127.0.0.1:6379> lpush city yunan guizhou hainan guangdong
(integer) 8  //city: (head)guangdong hainan guizhou yunan shanghai hubei beijing hunan(tail)
127.0.0.1:6379> lrange city 2 -3
1) "guizhou"
2) "yunan"
3) "shanghai"
4) "hubei"
127.0.0.1:6379> lrange city -1 2  //注意顺序,start必须在end的左边
(empty list or set)
127.0.0.1:6379> lrange city -2 -1
1) "beijing"
2) "hunan"
127.0.0.1:6379> llen city
(integer) 8
127.0.0.1:6379> lpop city
"guangdong"
127.0.0.1:6379> rpop city
"hunan"
127.0.0.1:6379> lpop city
"hainan"
127.0.0.1:6379> rpop city
"beijing"
//city: (head)guizhou yunan shanghai hubei(tail)
127.0.0.1:6379> lrange city 0 -1
1) "guizhou"
2) "yunan"
3) "shanghai"
4) "hubei"127.0.0.1:6379> del city
(integer) 1
127.0.0.1:6379> llen city
(integer) 0

2.4、Set(集合)

Redis的Set是string类型的无序集合,其元素不可重复,底层的数据结构是HashTable

主要方法

  • sadd key member [member …]。将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略
  • smembers key。返回集合 key 中的所有成员。不存在的 key 被视为空集合。
  • sismember key member。判断 member 元素是否集合 key 的成员。
  • srem key member [member …]。移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略。
127.0.0.1:6379> sadd subject yuwen shuxue yingyu wuli huaxue
(integer) 5
127.0.0.1:6379> smembers subject
1) "wuli"
2) "yuwen"
3) "yingyu"
4) "shuxue"
5) "huaxue"
127.0.0.1:6379> sismember subject shuxue
(integer) 1
127.0.0.1:6379> sismember subject shengwu
(integer) 0
127.0.0.1:6379> srem subject wuli yingyu huaxue dili shengwu
(integer) 3
127.0.0.1:6379> smembers subject
1) "yuwen"
2) "shuxue"
127.0.0.1:6379> del subject
(integer) 1
127.0.0.1:6379> smembers subject

2.5、zset(有序集合)

zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。但是,与set不同的是, zset 每个 member 后面都携带一个 score ,可以用作排序;score 值可以是整数值或双精度浮点数,并且可以相等。因此, zset 可以进行排序

主要方法

  • zadd key score member [[score member] [score member] …]。将一个或多个 member 元素及其 score 值加入到有序集 key 当中。如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。
  • zscore key member。返回有序集 key 中,成员 member 的 score 值。如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil
  • zrange key start stop [WITHSCORES]。返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序。具有相同 score 值的成员按字典序(lexicographical order )来排列。
  • zrevrange key start stop [WITHSCORES]。成员的位置按 score 值递增(从大到小)来排序
  • zrank key member。返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。排名以 0 为底,也就是说, score 值最小的成员排名为 0 。
  • zcount key min max。返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。
  • zrem key member [member …]。移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。
127.0.0.1:6379> zadd page 10 google.com 9 baidu.com 8 bing.com 5 sougo.com
(integer) 4
127.0.0.1:6379> zrange page 1 -1
1) "bing.com"
2) "baidu.com"
3) "google.com"
127.0.0.1:6379> zrange page 1 -2 withscores
1) "bing.com"
2) "8"
3) "baidu.com"
4) "9"
127.0.0.1:6379> zrevrange page 0 -1
1) "google.com"
2) "baidu.com"
3) "bing.com"
4) "sougo.com"
127.0.0.1:6379> zrank page sougo.com
(integer) 0
127.0.0.1:6379> zrank page bing.com
(integer) 1127.0.0.1:6379> zrevrank page google.com
(integer) 0
127.0.0.1:6379>
127.0.0.1:6379> zcount page 8 9
(integer) 2
127.0.0.1:6379> zrem page baidu.com 360.com sougo.com
(integer) 2
127.0.0.1:6379> zrange page 0 -1
1) "bing.com"
2) "google.com"

3、go连接redis

3.1、下载工具包

主要推荐两个(下载其中一个即可)
(1)github.com/gomodule/redigo/redis
(2)github.com/go-redis/redis

下载方式
(1)命令行中直接下载

go get github.com/gomodule/redigo/redis
go get github.com/go-redis/redis

(2)进入对应的网址下载压缩包解压

3.2、连接redis数据库

import ("fmt""time""github.com/gomodule/redigo/redis"
)func main() {//1. 连接redis数据库con, err := redis.Dial("tcp", "localhost:6379")if err != nil {fmt.Println("redis.Dial err = ", err)return}defer con.Close()//2. 向redis中写、读数据//2.1 写、读string数据//(1)写数据_, err = con.Do("set", "name", "mary")if err != nil {fmt.Println("redis-string:\t set key:name failed, err = ", err)return}//(2)读数据string_str, err := redis.String(con.Do("get", "name"))if err != nil {fmt.Println("redis-string:\t get key-name failed, err = ", err)return}fmt.Println("redis-string:\t get key-name, value = ", string_str)//(3)设置有效时间为1s_, err = con.Do("expire", "name", 1)if err != nil {fmt.Println("redis-string:\t set key-name expire-time failed, err = ", err)return}fmt.Println("redis-string:\t set key-name expire-time to 1s and sleep 1s")//(4)等待1s后再次读取time.Sleep(time.Second) //等待1秒钟string_str, err = redis.String(con.Do("get", "name"))if err != nil {fmt.Println("redis-string:\t get key:name failed, err = ", err)} else {fmt.Println("redis-string:\t get key-name, value = ", string_str)}//2.2 写、读hash数据//(1)批量写数据_, err = con.Do("hmset", "person1", "sex", "man", "age", 30, "addr", "wuhan")if err != nil {fmt.Println("\nhmset redis-hash key:person1 failed, err = ", err)return}//(2)写单个field的数据_, err = con.Do("hset", "person1", "mail", "zs@qq.com")if err != nil {fmt.Println("\nredis-hash:\t hset key:person1 failed, err = ", err)return}//(3)读单个field的数据hash_age_str, err := redis.Int(con.Do("hget", "person1", "age"))if err != nil {fmt.Println("\nredis-hash:\t hget key:person1 failed, err = ", err)return}fmt.Println("\nredis-hash:\t hget key-person1, field-age: value = ", hash_age_str)//(4)批量读数据hash_getall_str, err := redis.Strings(con.Do("hgetall", "person1"))if err != nil {fmt.Println("redis-hash:\t hgetall key:person1 failed, err = ", err)return}fmt.Println("redis-hash:\t hgetall key-person1, all field and value = ", hash_getall_str)
}
redis-string:     get key-name, value =  mary
redis-string:    set key-name expire-time to 1s and sleep 1s
redis-string:    get key:name failed, err =  redigo: nil returnedredis-hash:    hget key-person1, field-age: value =  30
redis-hash:  hgetall key-person1, all field and value =  [name ZhangSan mail zs@qq.com sex man age 30 addr wuhan]

3.3、redis连接池

为什么需要连接池:
在操作数据时,需要先获得连接,使用完成后还有关闭连接,这两个操作都比较耗时,当频繁对数据库进行操作时,程序将会耗费大量的时间在建立连接和关闭连接上。因此需要一个已经建立了多个连接的缓冲区,需要操作数据库的时候从缓冲区中取,用完了再还回去,如此可以确保快速操作数据库,提高了效率,这个缓冲区就是连接池

import ("fmt""github.com/gomodule/redigo/redis"
)var pool *redis.Poolfunc init() {pool = &redis.Pool{MaxIdle:     8,   //最大空闲连接数MaxActive:   0,   //与数据库的最大连接数,0表示无限制IdleTimeout: 100, //最大空闲时间Dial: func() (redis.Conn, error) {return redis.Dial("tcp", "localhost:6379")},}
}func main() {//1. 先获取1个连接con := pool.Get()defer con.Close()_, err := con.Do("set", "addr", "HuBei")if err != nil {fmt.Println("redis-string:\t set key:addr failed, err = ", err)return}string_str, err := redis.String(con.Do("get", "addr"))if err != nil {fmt.Println("redis-string:\t get key-addr failed, err = ", err)return}fmt.Println("redis-string:\t get key-addr, value = ", string_str)
}output:
redis-string:    get key-addr, value =  HuBei

Go语言学习笔记【6】 单元测试、Redis基础相关推荐

  1. C 语言学习笔记(二):编程基础

    目录 一.冯诺依曼模型 二.程序语言发展历史 三.进制 3.1 二进制 3.2 八进制 3.3 十六进制 3.4 进制转换:二进制.八进制.十六进制.十进制之间的转换 3.4.1 将二进制.八进制.十 ...

  2. 《Go语言圣经》学习笔记 第三章 基础数据类型

    <Go语言圣经>学习笔记 第三章 基础数据类型 目录 整型 浮点数 复数 布尔型 字符串 常量 注:学习<Go语言圣经>笔记,PDF点击下载,建议看书. Go语言小白学习笔记, ...

  3. go get 拉取指定版本_go语言学习笔记-基础知识-3

    相关文档 go语言学习笔记-目录 1.简介 1.1 什么是GO Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易.Go是从2007年末由Robert Griesemer, Rob ...

  4. 易语言学习笔记——基础篇

    易语言学习笔记20180710 一. 易语言的数据类型可以分为基本数据类型和特殊数据类型 1.     其中基本数据类型分为: ①   数值型 ②   逻辑型 ③   日期时间型 ④   文本型 ⑤  ...

  5. 【Go语言 · 学习笔记】

    文章目录 Go语言 · 学习笔记 一.Go包管理 1. 什么是Go语言中的包 2. 包的命名 3. main包 4. 导入包 5. 远程包导入 6. 命名导入 7. 包的init函数 二.Go开发工具 ...

  6. XML学习笔记01【xml_基础、xml_约束】

    Java后端 学习路线 笔记汇总表[黑马程序员] XML学习笔记01[xml_基础.xml_约束][day01] XML学习笔记02[xml_解析][day01] 目录 01 xml_基础 今日内容 ...

  7. python表单提交的两种方式_Flask框架学习笔记之表单基础介绍与表单提交方式

    本文实例讲述了Flask框架学习笔记之表单基础介绍与表单提交方式.分享给大家供大家参考,具体如下: 表单介绍 表单是HTML页面中负责数据采集功能的部件.由表单标签,表单域和表单按钮组成.通过表单,将 ...

  8. C语言学习笔记-P1 初识C语言(1)

    C语言学习笔记-P1 初识C语言(1) P1 初识C语言(1) 一.什么是C语言 1.定义 2.发展 二.第一个C语言程序 Hello World 三.数据类型 四.变量,常量 未完待续!!! P1 ...

  9. MATLAB学习笔记2:MATLAB基础知识(下)

    阅读前请注意: 1. 该学习笔记是华中师范大学HelloWorld程序设计协会2021年寒假MATLAB培训的学习记录,是基于培训课堂内容的总结归纳.拓展阅读.博客内容由 @K2SO4钾 撰写.编辑, ...

  10. R语言学习笔记(1~3)

    R语言学习笔记(1~3) 一.R语言介绍 x <- rnorm(5) 创建了一个名为x的向量对象,它包含5个来自标准正态分布的随机偏差. 1.1 注释 由符号#开头. #函数c()以向量的形式输 ...

最新文章

  1. java多线程基础篇第二篇-volidate关键字
  2. Tomcat无法访问中文路径的解决办法
  3. 网络流 增广路 回退
  4. java builder pool_每周10道Java面试题:String, String Pool, StringBuilder
  5. WordPress实践:上传文件时提示“缺少临时文件夹”
  6. linux创建用户已存在哪里,解决linux下创建用户时出现 Creating mailbox file: 文件已存在...
  7. qml 时间控件_Qt6官方最新消息:桌面样式Qt quick Controls 2支持大多控件,委托更少,运行更流畅...
  8. 天下谁人不识君:awt如何使用弹窗功能?
  9. oracle叶子节点函数,oracle tree计算叶子节点到根节点的乘积
  10. 一款PDF解密工具的Keygen
  11. 小白入门 - PHP简介
  12. Windows 7 新功能 - AppLocker
  13. centos7安装python3.7.4_基于centos7 安装python3.6.4出错的解决方法
  14. Controller层各注解总结
  15. 公安网络及计算机信息系统安全,违反公安网络和信息安全保密工作规定及公安机关有关公安网络、计算机和信息应用系..._考试资料网...
  16. Python文件读写代码
  17. 互斥事件的概念和公式_互斥事件
  18. 增长黑客AB-Testing系统设计
  19. 本地游升温,银泰百货成新晋打卡热门地
  20. 霍尔速度传感器工作原理与应用

热门文章

  1. 【李佳辉_周报_2022.10.2】
  2. python打印日志(控制台内容输出)
  3. 简述c语言中break的作用,c语言break什么意思?
  4. mybatis json转对象Object
  5. 解决Windows环境下PHP连接MySQL很慢的问题
  6. 关于JS下offsetLeft,style.left,以及jquery中的offset().left,css(left)的区别。
  7. Elasticsearch常见搜索方法的实现
  8. detectron2 c++ 部署笔记
  9. 面试时,被问到职业规划如何作答?
  10. JavaScript图片轮播案例