在互联网后台数据存储组件中,Redis、Mysql、Mongodb是三个非常重要的存储组件,是SQL和NoSQL存储系统的典型代表,因此很有必要掌握这三大组件Go的基本操作。

Redis

go redis安装

安装和启动Redis

  1. sudo apt install redis-server
  2. sudo service redis-server start
  3. go get github.com/go-redis/redis/v8

通过cli连接redis

redis-cli -h 127.0.0.1 -p 6379

go redis的实践

redis 五大数据结构:

1.png

redis五大数据结构的使用实践案例如下:

package main

import (
    "context"
    "fmt"
    "time"
    "github.com/go-redis/redis/v8"
)

var ctx = context.Background()

func main() {
    rdb := redis.NewClient(&redis.Options{
        Addr:     "127.0.0.1:6379",
        Password: "",
        DB:       0,
    })

    pong, err := rdb.Ping(ctx).Result()
    if err != nil {
        fmt.Printf("连接redis出错,错误信息:%v", err)
        return
    } else {
        fmt.Println("成功连接redis,", pong)
    }


    // ======================key val get set============================================

    // set key val操作
    err = rdb.Set(ctx, "guid", "89_1909979_2232118", 0).Err()
    if err != nil {
        fmt.Printf("redis set失败,错误信息:%v", err)
    }

    // get key val操作
    val, err := rdb.Get(ctx, "guid").Result()
    if err != nil {
        fmt.Printf("redis get失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis get成功,key:%s, val:%s\n", "guid", val)
    }

    // 删除一个key
    err = rdb.Del(ctx, "guid").Err()
    if err != nil {
        fmt.Printf("redis Del失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis Del成功,key:%s\n", "guid")
    }

    val, err = rdb.Get(ctx, "guidxx").Result()
    if err != nil {
        fmt.Printf("redis get失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis get成功,key:%s, val:%s\n", "guidxx", val)
    }

    // set key val NX, key不存在才set, 并设置指定过期时间
    err = rdb.SetNX(ctx, "task", "123", 10*time.Second).Err()
    if err != nil {
        fmt.Printf("redis SetNX失败,错误信息:%v\n", err)
    }

    time.Sleep(time.Duration(1)*time.Second)

    // 获取过期剩余时间
    tm, err := rdb.TTL(ctx, "task").Result()
    if err != nil {
        fmt.Printf("redis TTL失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis TTL成功,key:%s, tm:%v\n", "task", tm)
    }

    val, err = rdb.Get(ctx, "task").Result()
    if err != nil {
        fmt.Printf("redis get失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis get成功,key:%s, val:%s\n", "task", val)
    }

    time.Sleep(time.Duration(11)*time.Second)

    val, err = rdb.Get(ctx, "task").Result()
    if err != nil {
        fmt.Printf("redis get失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis get成功,key:%s, val:%s\n", "task", val)
    }

    // 对key设置newValue这个值,并且返回key原来的旧值。原子操作。
    oldVal, err := rdb.GetSet(ctx, "task", "456").Result()
    if err != nil {
        fmt.Printf("redis GetSet失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis GetSet成功,key:%s, oldVal:%s\n", "task", oldVal)
    }

    // 批量get set
    err = rdb.MSet(ctx, "key1", "val1", "key2", "val2", "key3", "val3").Err()
    if err != nil {
        fmt.Printf("redis MSet失败,错误信息:%v\n", err)
    } 

    vals, err := rdb.MGet(ctx, "key1", "key2", "key3").Result()
    if err != nil {
        fmt.Printf("redis MGet失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis MGet成功,vals:%v\n", vals)
    }

    // 自增自减,原子操作
    err = rdb.Incr(ctx, "age").Err()
    if err != nil {
        fmt.Printf("redis Incr失败,错误信息:%v\n", err)
    }
    // +5
    err = rdb.IncrBy(ctx, "age", 5).Err()
    if err != nil {
        fmt.Printf("redis IncrBy失败,错误信息:%v\n", err)
    }

    err = rdb.Decr(ctx, "age").Err()
    if err != nil {
        fmt.Printf("redisDecr失败,错误信息:%v\n", err)
    }
    // -3
    err = rdb.DecrBy(ctx, "age", 3).Err()
    if err != nil {
        fmt.Printf("redis DecrBy失败,错误信息:%v\n", err)
    } 

    // 2
    val, err = rdb.Get(ctx, "age").Result()
    if err != nil {
        fmt.Printf("redis get失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis get成功,key:%s, val:%s\n", "age", val)
    }

    // 对key设置过期时间
    rdb.Expire(ctx, "key1", 3*time.Second)

    tm, err = rdb.TTL(ctx, "key1").Result()
    if err != nil {
        fmt.Printf("redis TTL失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis TTL成功,key:%s, tm:%v\n", "key1", tm)
    }

    //批量删除
    err = rdb.Del(ctx, "key1", "key2", "key3").Err()
    if err != nil {
        fmt.Printf("redis Del失败,错误信息:%v\n", err)
    }

    // =====================list=============================

    // LPushX 从左往右插入
    // //仅当列表存在的时候才插入数据,此时列表不存在,无法插入
    err = rdb.LPushX(ctx, "uids", 120).Err()
    if err != nil {
        fmt.Printf("redis LPushX失败,错误信息:%v\n", err)
    }

    // /此时列表不存在,依然可以插入
    err = rdb.LPush(ctx, "uids", 130).Err()
    if err != nil {
        fmt.Printf("redis LPush失败,错误信息:%v\n", err)
    }

    // 批量插入
    err = rdb.LPushX(ctx, "uids", 130, 140, 154, 132).Err()
    if err != nil {
        fmt.Printf("redis LPush失败,错误信息:%v\n", err)
    }

    // 返回全部数据
    vals2, err := rdb.LRange(ctx, "uids", 0, -1).Result()
    if err != nil {
        fmt.Printf("redis LRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis LRange成功,key:%s, vals:%v\n", "uids", vals2)  // redis LRange成功,key:uids, vals:[132 154 140 130 130]
    }

    // 取队列[2,4]的数据,即第3,4,5位置数据
    vals2, err = rdb.LRange(ctx, "uids", 2, 4).Result()
    if err != nil {
        fmt.Printf("redis LRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis LRange成功,key:%s, vals:%v\n", "uids", vals2)  // redis LRange成功,key:uids, vals:[140 130 130]
    }

    // 返回队列长度
    llen, err := rdb.LLen(ctx, "uids").Result()
    if err != nil {
        fmt.Printf("redis LLen失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis LLen成功,key:%s, llen:%v\n", "uids", llen)  // redis LLen成功,key:uids, llen:5
    }

    // 修改list中指定位置的值
    err = rdb.LSet(ctx, "uids", 2, 1000).Err()
    if err != nil {
        fmt.Printf("redis LSet失败,错误信息:%v\n", err)
    }

    // 返回全部数据
    vals2, err = rdb.LRange(ctx, "uids", 0, -1).Result()
    if err != nil {
        fmt.Printf("redis LRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis LRange成功,key:%s, vals:%v\n", "uids", vals2)  //redis LRange成功,key:uids, vals:[132 154 1000 130 130]
    }

    // 出队列,左进右出
    err = rdb.RPop(ctx, "uids").Err()
    if err != nil {
        fmt.Printf("redis RPop失败,错误信息:%v\n", err)
    }

    vals2, err = rdb.LRange(ctx, "uids", 0, -1).Result()
    if err != nil {
        fmt.Printf("redis LRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis LRange成功,key:%s, vals:%v\n", "uids", vals2) 
    }


    // 出队列,左进右出。没有就会阻塞,可以设置阻塞超时值
    err = rdb.BRPop(ctx, time.Duration(1)*time.Second, "uids").Err()
    if err != nil {
        fmt.Printf("redis BRPop失败,错误信息:%v\n", err)
    }

    // 删除一定位置范围内的值。删除count个key的list中值为value 的元素。如果出现重复元素,仅删除1次,也就是删除第一个
    err = rdb.LRem(ctx, "uids", 3, 130).Err()
    if err != nil {
        fmt.Printf("redis LRem失败,错误信息:%v\n", err)
    }

    // 返回全部数据
    vals2, err = rdb.LRange(ctx, "uids", 0, -1).Result()
    if err != nil {
        fmt.Printf("redis LRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis LRange成功,key:%s, vals:%v\n", "uids", vals2)  //redis LRange成功,key:uids, vals:[132 154 1000]
    }

    // =====================================集合操作=============================
    //redis集合特性:元素无序且唯一

    // 批量入集合
    err = rdb.SAdd(ctx, "students", "Alice", "James", "James").Err()
    if err != nil {
        fmt.Printf("redis SAdd失败,错误信息:%v\n", err)
    }

    // 获取集合大小
    size, err := rdb.SCard(ctx, "students").Result()
    if err != nil {
        fmt.Printf("redis SCard失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis SCard成功,key:%s, size:%v\n", "students", size)  //redis SCard成功,key:students, size:2
    }

    // 返回集合所有元素
    sMem, err := rdb.SMembers(ctx, "students").Result()
    if err != nil {
        fmt.Printf("redis SMembers失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis SMembers成功,key:%s, size:%v\n", "students", sMem)  //redis SMembers成功,key:students, size:[James Alice]
    }

    // 判断元素是否在集合中
    flag, err := rdb.SIsMember(ctx, "students", "James").Result()
    if err != nil {
        fmt.Printf("redis SIsMember失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis SIsMember成功,key:%s, size:%v\n", "students", flag)  //redis SIsMember成功,key:students, size:true
    }

    // 删除集合元素
    err = rdb.SRem(ctx, "students", "Alice").Err()
    if err != nil {
        fmt.Printf("redis SRem失败,错误信息:%v\n", err)
    }

    // =============================hash操作========================
    // 多级嵌套HASH  China 是hash Guangdong 是字段名, Tencent是字段值
    err = rdb.HSet(ctx, "China", "Guangdong", "Tencent").Err()
    if err != nil {
        fmt.Printf("redisHSet失败,错误信息:%v\n", err)
    }

    hvar, err := rdb.HGet(ctx, "China", "Guangdong").Result()
    if err != nil {
        fmt.Printf("redis HGet失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis HGet成功,hvar:%v\n", hvar) 
    }

    err = rdb.HSet(ctx, "China", "Hanzhou", "Alibaba").Err()
    if err != nil {
        fmt.Printf("redis HSet失败,错误信息:%v\n", err)
    }

    // 返回的是个map
    hvarAll, err := rdb.HGetAll(ctx, "China").Result()
    if err != nil {
        fmt.Printf("redis HGetAll失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis HGetAll成功,hvarAll:%v\n", hvarAll)    //redis HGetAll成功,hvarAll:map[Guangdong:Tencent Hanzhou:Alibaba]
    }

    // 将map塞进hash
    batchData := make(map[string]interface{})
    batchData["username"] = "test"
    batchData["password"] = 123456
    err = rdb.HMSet(ctx, "users", batchData).Err()
    if err != nil {
        fmt.Printf("redis HMSet失败,错误信息:%v\n", err)
    }

    hvarAll, err = rdb.HGetAll(ctx, "users").Result()
    if err != nil {
        fmt.Printf("redis HGetAll失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis HGetAll成功,hvarAll:%v\n", hvarAll)   //redis HGetAll成功,hvarAll:map[password:123456 username:test]
    }

    // "Hanzhou"字段不存在才Set
    err = rdb.HSetNX(ctx, "China", "Hanzhou", "Netease").Err()
    if err != nil {
        fmt.Printf("redis HSetNX失败,错误信息:%v\n", err)
    }

    // 对key的值+n
    count, err := rdb.HIncrBy(ctx, "users", "password", 10).Result()
    if err != nil {
        fmt.Printf("redis HIncrBy失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis HIncrBy成功,count:%v\n", count)   // redis HIncrBy成功,count:123466
    }

    // 返回所有key,返回值是个string数组
    keys, err := rdb.HKeys(ctx, "China").Result()
    if err != nil {
        fmt.Printf("redisHKeys失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis HKeys成功,keys:%v\n", keys)   //redis HKeys成功,keys:[Guangdong Hanzhou]
    }

    // 根据key,查询hash的字段数量
    hlen, err := rdb.HLen(ctx, "China").Result()
    if err != nil {
        fmt.Printf("redis HLen失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis HLen成功,hlen:%v\n", hlen)   // redis HLen成功,hlen:2
    }

    //删除多个key
    err = rdb.HDel(ctx, "China", "Hanzhou", "Guangdong").Err()
    if err != nil {
        fmt.Printf("redis HDel失败,错误信息:%v\n", err)
    }

    //================================有序集合sort set================================================

    /*
        // Z 表示已排序的集合成员
        type Z struct {
            Score  float64  // 分数
            Member interface{} // 元素名
        }
    */
    zsetKey := "companys_rank"
    companys := []*redis.Z{
        {Score: 100.0, Member: "Apple"},
        {Score: 90.0, Member: "MicroSoft"},
        {Score: 70.0, Member: "Amazon"},
        {Score: 87.0, Member: "Google"},
        {Score: 77.0, Member: "Facebook"},
        {Score: 67.0, Member: "Tesla"},
    }

    err = rdb.ZAdd(ctx, zsetKey, companys...).Err()
    if err != nil {
        fmt.Printf("redis ZAdd失败,错误信息:%v\n", err)
    }

    err = rdb.ZIncrBy(ctx, zsetKey, 2, "Amazon").Err()
    if err != nil {
        fmt.Printf("redis ZIncrBy失败,错误信息:%v\n", err)
    }

    //返回从0到-1位置的集合元素, 元素按分数从小到大排序 
    rank, err := rdb.ZRange(ctx, zsetKey, 0, -1).Result()
    if err != nil {
        fmt.Printf("redis ZRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis ZRange成功,rank:%v\n", rank)   //redis ZRange成功,rank:[Tesla Amazon Facebook Google MicroSoft Apple]
    }  

    //返回top3
    rank, err = rdb.ZRange(ctx, zsetKey, -3, -1).Result()
    if err != nil {
        fmt.Printf("redis ZRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis ZRange成功,rank:%v\n", rank)   //redis ZRange成功,rank:[Google MicroSoft Apple]
    }  

    op := &redis.ZRangeBy{
        Min:"80", // 最小分数
        Max:"100", // 最大分数
        Offset:0, // 类似sql的limit, 表示开始偏移量
        Count:2, // 一次返回多少数据
    }

    ///根据分数范围返回集合元素,实现排行榜,取top n
    rank, err = rdb.ZRangeByScore(ctx, zsetKey, op).Result()
    if err != nil {
        fmt.Printf("redis ZRangeByScore失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis ZRangeByScore成功,rank:%v\n", rank)   //redis ZRangeByScore成功,rank:[Google MicroSoft]
    } 

    //根据元素名,查询集合元素在集合中的排名,从0开始算,集合元素按分数从小到大排序
    rk, err := rdb.ZRank(ctx, zsetKey, "Apple").Result()
    if err != nil {
        fmt.Printf("redis ZRank失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis ZRank成功,rk:%v\n", rk)  // redis ZRank成功,rk:5
    } 

    // 一次删除多个key
    err = rdb.ZRem(ctx, zsetKey, "Apple", "Amazon").Err()
    if err != nil {
        fmt.Printf("redis ZRem失败,错误信息:%v\n", err)
    }

    //集合元素按分数排序,从最低分到高分,删除第0个元素到第1个元素。 这里相当于删除最低分的2个元素
    err = rdb.ZRemRangeByRank(ctx, zsetKey, 0, 1).Err()
    if err != nil {
        fmt.Printf("redis ZRemRangeByRank失败,错误信息:%v\n", err) 
    }

    rank, err = rdb.ZRange(ctx, zsetKey, 0, -1).Result()
    if err != nil {
        fmt.Printf("redis ZRange失败,错误信息:%v\n", err)
    } else {
        fmt.Printf("redis ZRange成功,rank:%v\n", rank)     //redis ZRange成功,rank:[Google MicroSoft]
    }  

}

输出

成功连接redis, PONG
redis get成功,key:guid, val:89_1909979_2232118
redis Del成功,key:guid
redis get失败,错误信息:redis: nil
redis TTL成功,key:task, tm:-1ns
redis get成功,key:task, val:456
redis get成功,key:task, val:456
redis GetSet成功,key:task, oldVal:456
redis MGet成功,vals:[val1 val2 val3]
redis get成功,key:age, val:60
redis TTL成功,key:key1, tm:3s
redis LRange成功,key:uids, vals:[132 154 140 130 130]
redis LRange成功,key:uids, vals:[140 130 130]
redis LLen成功,key:uids, llen:5
redis LRange成功,key:uids, vals:[132 154 1000 130 130]
redis LRange成功,key:uids, vals:[132 154 1000 130]
redis LRange成功,key:uids, vals:[132 154 1000]
redis SCard成功,key:students, size:2
redis SMembers成功,key:students, size:[Alice James]
redis SIsMember成功,key:students, size:true
redis HGet成功,hvar:Tencent
redis HGetAll成功,hvarAll:map[Guangdong:Tencent Hanzhou:Alibaba]
redis HGetAll成功,hvarAll:map[password:123456 username:test]
redis HIncrBy成功,count:123466
redis HKeys成功,keys:[Guangdong Hanzhou]
redis HLen成功,hlen:2
redis ZRange成功,rank:[Tesla Amazon Facebook Google MicroSoft Apple]
redis ZRange成功,rank:[Google MicroSoft Apple]
redis ZRangeByScore成功,rank:[Google MicroSoft]
redis ZRank成功,rk:5
redis ZRange成功,rank:[Google MicroSoft]

Mysql

命令行连接msyql

mysql -h 127.0.0.1 -P 3306 -uxy1 -pxy -A

mysql的CRUD实践案例:

package main

import (
    "fmt"

    _ "github.com/go-sql-driver/mysql"
    "github.com/jmoiron/sqlx"
)

type Person struct {
    Cguid    string    `db:"cguid"`
    Username string `db:"name"`
}

var Db *sqlx.DB

//init()函数会在每个包完成初始化后自动执行,并且执行优先级比main函数高。
func init() {

    database, err := sqlx.Open("mysql", "root:@tcp(127.0.0.1:9090)/pyc2021")
    if err != nil {
        fmt.Println("open mysql failed,", err)
        return
    }

    Db = database
}

func main() {

    // 查询
    var person []Person
    err := Db.Select(&person, "select cguid, name from pyc2021_match limit 10;")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }

    fmt.Println("select succ:", person)

    //通过Db.Select方法将查询的多行数据保存在一个切片中,然后就可以通过循环的方式获取每行数据
    for _, info := range person {
        cguid := info.Cguid
        name := info.Username
        fmt.Println("mysql select, ", cguid, name)
    }

    // 插入
    r, err := Db.Exec("insert into pyc2021_match(cguid, vote, name, hostnum)values('781122223', 200, '这是一个测试', 90)")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }
    id, err := r.LastInsertId()
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }

    fmt.Println("insert succ:", id)

    // 更新
    res, err := Db.Exec("update pyc2021_match set name='修改测试' where cguid='98977999'")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }
    row, err := res.RowsAffected()
    if err != nil {
        fmt.Println("rows failed, ",err)
    }
    fmt.Println("update succ:",row)

    // 删除
    res, err = Db.Exec("delete from pyc2021_match where cguid='98977999'")
    if err != nil {
        fmt.Println("exec failed, ", err)
        return
    }

    row,err = res.RowsAffected()
    if err != nil {
        fmt.Println("rows failed, ",err)
    }

    fmt.Println("delete succ: ",row)

    Db.Close()
}

输出:

select succ: [{7822223 xxxx1} {7832223 xsxxx1} {7832233 xsx99} {22223 西红柿} {98977999 修改测试} {78222223 这是一个测试} {78122223 这是一个测试}]
mysql select,  7822223 xxxx1
mysql select,  7832223 xsxxx1
mysql select,  7832233 xsx99
mysql select,  22223 西红柿
mysql select,  98977999 修改测试
mysql select,  78222223 这是一个测试
mysql select,  78122223 这是一个测试
insert succ: 12
update succ: 0
delete succ:  1

Mongodb

命令行连接mongodb

mongo mongodb://root:123@127.0.0.1:30002/xyq

mongodb实践

mongodb的CRUD实践如下:

package main

//https://github.com/tfogo/mongodb-go-tutorial

import (
   "go.mongodb.org/mongo-driver/bson"    //BOSN解析包
   "go.mongodb.org/mongo-driver/mongo"    //MongoDB的Go驱动包
   "go.mongodb.org/mongo-driver/mongo/options"
   "fmt"
   "log"
   "context"
)

type Users struct {
    Cguid string   `bson:"cguid"`
   Uid   int      `bson:"uid"`
   Text  string   `bson:"text"`
   Name  string   `bson:"name"`
}


func main() {

   //var ctx context.Context
   clientOptions := options.Client().ApplyURI("mongodb://root:mg@192.168.44.105:30002/xyq")

   // 建立客户端连接
   client, err := mongo.Connect(context.TODO(), clientOptions)
   if err != nil {
      log.Fatal(err)
      fmt.Println(err)
   }

   // 检查连接情况
   err = client.Ping(context.TODO(), nil)
   if err != nil {
      log.Fatal(err)
      fmt.Println(err)
   }
   fmt.Println("Connected to MongoDB!")

   //指定要操作的数据集
  // collection := client.Database("xyq").Collection("ljs_test")
   collection := client.Database("xyq").Collection("pyc2021_rank")

   //执行增删改查操作

   //插入一条数据
   newUser := Users{"89_34122417_1642765091", 129829, "新的文本", "sorrymaker"}
   res, err := collection.InsertOne(context.TODO(), newUser) 
   if err != nil { 
         log.Fatal(err) 
   } 
   fmt.Println("Inserted document: ", res.InsertedID) 

   //插入多条数据

   newUser1 := Users{"89_21932437_1643320091", 139829, "新的文本1", "sorrymaker"}
   newUser2 := Users{"89_31933227_164442021", 139129, "新的文本2", "sorrymaker"}
   newUser3 := Users{"89_41931237_1642121091", 139429, "新的文本3", "sorrymaker"}
   news := []interface{}{newUser1, newUser2, newUser3}
   res1, err := collection.InsertMany(context.TODO(), news) 
   if err != nil { 
         log.Fatal(err) 
   } 
   fmt.Println("Inserted document: ", res1.InsertedIDs) 

   // 查找一个数据
   var user Users
   filter := bson.D{{"cguid", "89_22932237_1649720099"}}
    if err = collection.FindOne(context.TODO(),filter).Decode(&user); err != nil{
        fmt.Println(err)
        return
    } 
   fmt.Printf("result:%+v\n", user)

   //查找多个符合条件的数据
   findOptions := options.Find()
   findOptions.SetLimit(10) //限制返回的条目
   var results []*Users
   filter = bson.D{{"name", "sorrymaker"}}
   cur, err := collection.Find(context.TODO(), filter, findOptions)
   if err != nil {
      fmt.Println(err)
        return
   }

   for cur.Next(context.TODO()) {
      var elem Users
      err := cur.Decode(&elem)
      if err != nil {
         fmt.Println(err)
         return
      }
      fmt.Printf("elem:%+v\n", elem)
      results = append(results, &elem)
   }

   if err := cur.Err(); err != nil {
      fmt.Println(err)
      return
   }
   cur.Close(context.TODO()) 


   //更新数据
   filter = bson.D{{"name", "sorrymaker"}} 
   update := bson.D{{"$set", bson.D{{"text", "修改成功"}}}} 
   updateResult, err := collection.UpdateOne(context.TODO(), filter, update) 
    if err != nil { 
         log.Fatal(err) 
    }
    fmt.Printf("Updated documents: %+v\n", updateResult) 


   //更新多条数据
   filter = bson.D{{"name", "sorrymaker"}} 
   update = bson.D{{"$set", bson.D{{"text", "udatemany修改成功"}}}} 
   updateResults, err := collection.UpdateMany(context.TODO(), filter, update) 
    if err != nil { 
         log.Fatal(err) 
    }
    fmt.Printf("UpdateMany documents: %+v\n", updateResults) 


   //更新数据,不存在就插入。upsert
   filter = bson.D{{"cguid", "89_22932437_1643120029"}} 
   update = bson.D{{"$set", bson.D{{"text", "修改成功upsert"}, {"cguid", "89_22932437_1643120029"}, {"uid",1982938}, {"name", "losjo"}}}} 
   updateOpts := options.Update().SetUpsert(true)  // 设置upsert模式
   updateResult, err = collection.UpdateOne(context.TODO(), bson.M{}, update, updateOpts)
   if err != nil {
       log.Fatal(err)
   }
   fmt.Printf("Upsert documents: %+v\n", updateResult) 

   // 删除一条数据
   filter = bson.D{{"cguid", "89_34922417_1641725099"}} 
   deleteResult, err := collection.DeleteOne(context.TODO(), filter)
   if err != nil {
      log.Fatal(err)
   }
   fmt.Printf("deleteone documents: %+v\n", deleteResult) 


   //给字段加索引
   indexModel := mongo.IndexModel{
      Keys: bson.D{
         {"name", 1},
      },
   }
   _, err = collection.Indexes().CreateOne(context.TODO(), indexModel)
   if err != nil {
      log.Fatal(err)
   }

   // 断开客户端连接
   err = client.Disconnect(context.TODO())
   if err != nil {
      log.Fatal(err)
   }
   fmt.Println("Connection to MongoDB closed.")
}

输出:

Connected to MongoDB!
Inserted document:  ObjectID("60a0a872d7ed08cd629ddabd")
Inserted document:  [ObjectID("60a0a872d7ed08cd629ddabe") ObjectID("60a0a872d7ed08cd629ddabf") ObjectID("60a0a872d7ed08cd629ddac0")]
result:{Cguid:89_22932237_1649720099 Uid:139829 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_32933237_1644720299 Uid:139129 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_42931237_1642721099 Uid:139429 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_42931237_1642121099 Uid:139429 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_42931237_1649721099 Uid:139429 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_32932417_1649725099 Uid:129829 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_22932237_1643720099 Uid:139829 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_32932237_1649720099 Uid:129829 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_32932237_1619720099 Uid:129829 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_32933237_1649720299 Uid:139129 Text:udatemany修改成功 Name:sorrymaker}
elem:{Cguid:89_22933237_1649720299 Uid:139129 Text:udatemany修改成功 Name:sorrymaker}
Updated documents: &{MatchedCount:1 ModifiedCount:1 UpsertedCount:0 UpsertedID:<nil>}
UpdateMany documents: &{MatchedCount:31 ModifiedCount:5 UpsertedCount:0 UpsertedID:<nil>}
Upsert documents: &{MatchedCount:1 ModifiedCount:1 UpsertedCount:0 UpsertedID:<nil>}
deleteone documents: &{DeletedCount:1}
Connection to MongoDB closed.