使用腾讯云go sdk 查询对象存储中最新文件

news2024/11/17 11:51:10

背景:

腾讯云账号下,有很多对象存储COS桶:
image.png
我现在想确认某一个对象存储桶的活跃程度,简单的来说。我想知道这个桶里面最后上传的一个文件是什么,以及它的上传时间戳。
本文将介绍如何使用腾讯云对象存储(COS)的 Go 语言 SDK 查询指定存储桶中的最新文件信息,包括文件路径和上传时间。本教程假设读者已经具备基本的 Go 语言编程知识,并且对腾讯云 COS 有一定的了解。

使用腾讯云go sdk 查询对象存储中最新文件

前置条件

  • 您需要拥有一个腾讯云账号,并创建了至少一个COS存储桶。
  • 了解Go语言和基本的并发编程知识。
  • 确保您已安装Go运行时环境。

安装腾讯云COS Go SDK

在开始之前,先确保您的开发环境已安装了腾讯云COS的Go SDK。如果尚未安装,可以使用以下Go命令安装:

mkdir xxxx
go mod int xxxx
go get github.com/tencentyun/cos-go-sdk-v5

我们这里的操作是属于List Object 参照:GetBucket
image.png

第一版代码:

使用chatgpt生成第一版代码:
main.go

package main

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"sort"
	"time"

	"github.com/tencentyun/cos-go-sdk-v5"
)

// 请替换下面的假设值为实际的 SecretId、SecretKey、BucketName 和 Region。
const (
	SecretId     = "xxxxxx"
	SecretKey    = "xxxx"
	BucketName   = "xxxxxx" // 例如 "example-1250000000"
	BucketRegion = "ap-shanghai"      // 例如 "ap-guangzhou"
)

func main() {
	u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", BucketName, BucketRegion))
	b := &cos.BaseURL{BucketURL: u}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  SecretId,
			SecretKey: SecretKey,
		},
	})

	c := context.Background()
	opt := &cos.BucketGetOptions{
		MaxKeys: 1000, // 修改这个值以获取更多或更少的对象
	}

	v, _, err := client.Bucket.Get(c, opt)
	if err != nil {
		panic(err)
	}

	// 对结果进行排序,找到最后更新的对象
	if len(v.Contents) > 0 {
		sort.Slice(v.Contents, func(i, j int) bool {
			ti, _ := time.Parse(time.RFC3339, v.Contents[i].LastModified)
			tj, _ := time.Parse(time.RFC3339, v.Contents[j].LastModified)
			return ti.After(tj)
		})
		lastUpdatedObj := v.Contents[0]
		fmt.Printf("最新上传文件路径: %s\n", lastUpdatedObj.Key)
		fmt.Printf("最新上传时间: %s\n", lastUpdatedObj.LastModified)
	} else {
		fmt.Println("桶中没有文件。")
	}
}

运行main.go

go run main.go

image.png
运行后也许感觉是正确的,毕竟没有报错。但是这里是有问题的,为什么呢?因为我本身不知道最后一个文件是什么,我手动上传了一个文件,最后一个文件应该是输出:go1.22.0.linux-amd64.tar.gz!
image.png
什么原因呢?问题应该是在这里:

	c := context.Background()
	opt := &cos.BucketGetOptions{
		MaxKeys: 1000, // 修改这个值以获取更多或更少的对象
	}

image.png
marker标记参数没有设置
继续修改完善main.go代码:

package main

import (
	"context"
	"fmt"
	"net/http"
	"net/url"
	"sort"
	"time"

	"github.com/tencentyun/cos-go-sdk-v5"
)

// 请替换以下的假设值为实际的 SecretId、SecretKey、BucketName 和 Region。
const (
	SecretId     = "xxxxxx"
	SecretKey    = "xxxx"
	BucketName   = "xxxxxx" // 例如 "example-1250000000"
	BucketRegion = "ap-shanghai"      // 例如 "ap-guangzhou"
)

func main() {
	u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", BucketName, BucketRegion))
	b := &cos.BaseURL{BucketURL: u}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  SecretId,
			SecretKey: SecretKey,
		},
	})

	c := context.Background()

	var lastUpdatedObj *cos.Object
	isTruncated := true
	nextMarker := ""

	for isTruncated {
		opt := &cos.BucketGetOptions{
			Marker:   nextMarker,
			MaxKeys:  1000, // 单次请求返回的最大对象数
		}

		v, _, err := client.Bucket.Get(c, opt)
		if err != nil {
			panic(err)
		}

		for _, object := range v.Contents {
			if lastUpdatedObj == nil || object.LastModified > lastUpdatedObj.LastModified {
				lastUpdatedObj = &object
			}
		}

		// 更新下一个标记和是否截断的标志
		isTruncated = v.IsTruncated
		nextMarker = v.NextMarker
	}

	// 检查是否有对象被找到
	if lastUpdatedObj != nil {
		fmt.Printf("最新上传文件路径: %s\n", lastUpdatedObj.Key)
		fmt.Printf("最新上传时间: %s\n", lastUpdatedObj.LastModified)
	} else {
		fmt.Println("桶中没有文件。")
	}
}

运行修改后的main.go文件:

go run main.go

image.png
输出go1.22.0.linux-amd64.tar.gz这个起码是正确的!

拆分代码

想继续拆分一下,将客户端的创建和查找逻辑拆分到两个独立的函数createCOSClient getLastUpdatedFileInfo,然后main函数中调用

package main

import (
	"context"
	"fmt"
	"github.com/tencentyun/cos-go-sdk-v5"
	"net/http"
	"net/url"
	"sort"
	"time"
)

// 请替换下面的假设值为实际的 SecretId、SecretKey、BucketName 和 Region。
const (
	SecretId     = "xxxxxx"
	SecretKey    = "xxx"
	BucketName   = "xxxxx" // 例如 "example-1250000000"
	BucketRegion = "ap-shanghai"      // 例如 "ap-guangzhou"
)

// 创建 COS 客户端
func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client {
	u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion))
	b := &cos.BaseURL{BucketURL: u}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  secretId,
			SecretKey: secretKey,
		},
	})
	return client
}
func getLastUpdatedFileInfo(client *cos.Client) (key, lastModifiedTime string, err error) {
	c := context.Background()

	// 初始化一个空字符串,表示从桶的开头获取文件列表
	nextMarker := ""
	var allContents []cos.Object

	for {
		opt := &cos.BucketGetOptions{
			MaxKeys: 1000,
			Marker:  nextMarker,
		}

		v, _, err := client.Bucket.Get(c, opt)
		if err != nil {
			return "", "", err
		}

		allContents = append(allContents, v.Contents...)

		// 如果没有更多的文件,则停止循环
		if !v.IsTruncated {
			break
		}

		// 更新 nextMarker 为下一页的开始位置
		nextMarker = v.NextMarker
	}

	// 对所有结果进行排序以找到最新更新的对象
	if len(allContents) > 0 {
		sort.Slice(allContents, func(i, j int) bool {
			ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified)
			tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified)
			if errTi != nil || errTj != nil {
				fmt.Printf("Error parsing time: %v, %v", errTi, errTj)
				return false
			}
			return ti.After(tj)
		})
		lastUpdatedObj := allContents[0]
		return lastUpdatedObj.Key, lastUpdatedObj.LastModified, nil
	} else {
		return "", "", fmt.Errorf("桶中没有文件")
	}
}

func main() {
	client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion)
	key, lastModifiedTime, err := getLastUpdatedFileInfo(client)
	if err != nil {
		fmt.Printf("\n查询失败: %v\n", err)
		return
	}

	fmt.Printf("\n最后更新的文件:\n")
	fmt.Printf("文件路径: %s\n", key)
	fmt.Printf("最后修改时间: %s\n", lastModifiedTime)
}

运行main.go

go run main.go

image.png
注:为了验证代码有效性,我这里后面又加了一个新的文件:zaZTYa1i2x.txt

加个进度条

上面的代码已经可以正常满足需求了,但是我新加一个进度条,显示查询了多少文件了。也能大概知道一个进度的状况,继续修改一下main.go

package main

import (
	"context"
	"fmt"
	"github.com/tencentyun/cos-go-sdk-v5"
	"net/http"
	"net/url"
	"sort"
	"time"
)

// 请替换下面的假设值为实际的 SecretId、SecretKey、BucketName 和 Region。
const (
	SecretId     = "xxxx"
	SecretKey    = "xxxxx"
	BucketName   = "xxxxx" // 例如 "example-1250000000"
	BucketRegion = "ap-shanghai"      // 例如 "ap-guangzhou"
)

// 创建 COS 客户端
func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client {
	u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion))
	b := &cos.BaseURL{BucketURL: u}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  secretId,
			SecretKey: secretKey,
		},
	})
	return client
}
func getLastUpdatedFileInfo(client *cos.Client) (key, lastModifiedTime string, err error) {
	c := context.Background()

	nextMarker := ""
	var allContents []cos.Object
	var retrievedCount int

	fmt.Println("开始检索文件列表...")

	for {
		opt := &cos.BucketGetOptions{
			MaxKeys: 10000,
			Marker:  nextMarker,
		}

		v, _, err := client.Bucket.Get(c, opt)
		if err != nil {
			return "", "", err
		}

		retrievedCount += len(v.Contents)
		fmt.Printf("已检索 %d 个文件...\r", retrievedCount) // 输出进度信息 '\r' 会覆盖当前行,这样我们就可以在同一行更新进度

		allContents = append(allContents, v.Contents...)

		if !v.IsTruncated {
			break
		}

		nextMarker = v.NextMarker
	}

	fmt.Println("\n文件列表检索完成。")

	if len(allContents) > 0 {
		sort.Slice(allContents, func(i, j int) bool {
			ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified)
			tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified)
			if errTi != nil || errTj != nil {
				fmt.Printf("Error parsing time: %v, %v", errTi, errTj)
				return false
			}
			return ti.After(tj)
		})
		lastUpdatedObj := allContents[0]
		return lastUpdatedObj.Key, lastUpdatedObj.LastModified, nil
	} else {
		return "", "", fmt.Errorf("桶中没有文件")
	}
}

func main() {
	client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion)
	key, lastModifiedTime, err := getLastUpdatedFileInfo(client)
	if err != nil {
		fmt.Printf("\n查询失败: %v\n", err)
		return
	}

	fmt.Printf("\n最后更新的文件:\n")
	fmt.Printf("文件路径: %s\n", key)
	fmt.Printf("最后修改时间: %s\n", lastModifiedTime)
}

运行main.go

go run main.go

image.png

继续完善

继续完善一下代码:我需要把MaxKeys 提取出来,增加一下输出程序的运行时间,并把输出文件的时间戳调整为东八区时间:

package main

import (
	"context"
	"fmt"
	"github.com/tencentyun/cos-go-sdk-v5"
	"net/http"
	"net/url"
	"sort"
	"time"
)

const (
	SecretId     = "xxxx"
	SecretKey    = "xxxxx"
	BucketName   = "xxxxx"
	BucketRegion = "ap-shanghai"
	MaxKeys      = 1000 // 设置最大检索数量的常量
)

var cstZone = time.FixedZone("CST", 8*3600) // 东八区时区

func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client {
	u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion))
	b := &cos.BaseURL{BucketURL: u}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  secretId,
			SecretKey: secretKey,
		},
	})
	return client
}

func getLastUpdatedFileInfo(client *cos.Client) (key, lastModifiedTime string, err error) {
	c := context.Background()

	nextMarker := ""
	var allContents []cos.Object
	var retrievedCount int

	fmt.Println("开始检索文件列表...")

	for {
		opt := &cos.BucketGetOptions{
			MaxKeys: MaxKeys, // 使用常量 MaxKeys
			Marker:  nextMarker,
		}

		v, _, err := client.Bucket.Get(c, opt)
		if err != nil {
			return "", "", err
		}

		retrievedCount += len(v.Contents)
		fmt.Printf("已检索 %d 个文件...\r", retrievedCount)

		allContents = append(allContents, v.Contents...)

		if !v.IsTruncated {
			break
		}

		nextMarker = v.NextMarker
	}

	fmt.Println("\n文件列表检索完成。")

	if len(allContents) > 0 {
		sort.Slice(allContents, func(i, j int) bool {
			ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified)
			tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified)
			if errTi != nil || errTj != nil {
				fmt.Printf("Error parsing time: %v, %v", errTi, errTj)
				return false
			}
			return ti.After(tj)
		})

		lastUpdatedObj := allContents[0]
		// 将文件的 LastModified 时间字符串转换为 time.Time
		t, err := time.Parse(time.RFC3339, lastUpdatedObj.LastModified)
		if err != nil {
			return "", "", fmt.Errorf("无法解析最后修改时间: %v", err)
		}
		// 转换为东八区时间
		cstTime := t.In(cstZone).Format(time.RFC3339)
		return lastUpdatedObj.Key, cstTime, nil
	} else {
		return "", "", fmt.Errorf("桶中没有文件")
	}
}

func main() {
	start := time.Now() // 程序开始时间

	client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion)
	key, lastModifiedTime, err := getLastUpdatedFileInfo(client)
	if err != nil {
		fmt.Printf("\n查询失败: %v\n", err)
		return
	}

	fmt.Printf("\n最后更新的文件:\n")
	fmt.Printf("文件路径: %s\n", key)
	fmt.Printf("最后修改时间: %s\n", lastModifiedTime)

	elapsed := time.Since(start) // 程序执行时间
	fmt.Printf("\n程序运行时间: %s\n", elapsed)
}

运行修改后的main.go文件:

go run main.go

image.png

继续发散

继续发散一下,我需要输出最后上传的10个文件

package main

import (
	"context"
	"fmt"
	"github.com/tencentyun/cos-go-sdk-v5"
	"net/http"
	"net/url"
	"sort"
	"time"
)

// 请替换下面的假设值为实际的 SecretId、SecretKey、BucketName 和 Region。
const (
	SecretId      = "AKID7Mhwz45A9zqcCf4s07A7FIKKTlAiEf7M"
	SecretKey     = "KXbXL0unr2EaBsicYejj1GkEjO2jWOAg"
	BucketName    = "layabox-10028350" // 例如 "example-1250000000"
	BucketRegion  = "ap-shanghai"      // 例如 "ap-guangzhou"
	MaxKeys       = 1000               // 设置最大检索数量的常量
	NumberOfFiles = 10                 // 需要获取的最后更新的文件数量
)

var cstZone = time.FixedZone("CST", 8*3600) // 东八区时区

func createCOSClient(secretId, secretKey, bucketName, bucketRegion string) *cos.Client {
	u, _ := url.Parse(fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucketName, bucketRegion))
	b := &cos.BaseURL{BucketURL: u}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  secretId,
			SecretKey: secretKey,
		},
	})
	return client
}

func getLastUpdatedFileInfo(client *cos.Client, numberOfFiles int) ([]cos.Object, error) {
	c := context.Background()

	nextMarker := ""
	var allContents []cos.Object
	var retrievedCount int

	fmt.Println("开始检索文件列表...")

	for {
		opt := &cos.BucketGetOptions{
			MaxKeys: MaxKeys, // 使用常量 MaxKeys
			Marker:  nextMarker,
		}

		v, _, err := client.Bucket.Get(c, opt)
		if err != nil {
			return nil, err
		}

		retrievedCount += len(v.Contents)
		fmt.Printf("已检索 %d 个文件...\r", retrievedCount)

		allContents = append(allContents, v.Contents...)

		if !v.IsTruncated {
			break
		}

		nextMarker = v.NextMarker
	}

	fmt.Println("\n文件列表检索完成。")
	fmt.Printf("\n桶中总文件数: %d\n", len(allContents))

	if len(allContents) > 0 {
		sort.Slice(allContents, func(i, j int) bool {
			ti, errTi := time.Parse(time.RFC3339, allContents[i].LastModified)
			tj, errTj := time.Parse(time.RFC3339, allContents[j].LastModified)
			if errTi != nil || errTj != nil {
				fmt.Printf("Error parsing time: %v, %v", errTi, errTj)
				return false
			}
			return ti.After(tj)
		})

		// 截取切片以获取最后更新的numberOfFiles个文件
		if len(allContents) > numberOfFiles {
			allContents = allContents[:numberOfFiles]
		}

		// 返回最后更新的numberOfFiles个文件
		return allContents, nil
	} else {
		return nil, fmt.Errorf("桶中没有文件")
	}
}

func main() {
	start := time.Now() // 程序开始时间

	client := createCOSClient(SecretId, SecretKey, BucketName, BucketRegion)
	files, err := getLastUpdatedFileInfo(client, NumberOfFiles)
	if err != nil {
		fmt.Printf("\n查询失败: %v\n", err)
		return
	}

	fmt.Printf("\n最后更新的%d个文件:\n", NumberOfFiles)
	for _, file := range files {
		t, err := time.Parse(time.RFC3339, file.LastModified)
		if err != nil {
			fmt.Printf("无法解析文件 %s 的最后修改时间: %v\n", file.Key, err)
			continue
		}
		cstTime := t.In(cstZone).Format(time.RFC3339)
		fmt.Printf("文件路径: %s\n", file.Key)
		fmt.Printf("最后修改时间: %s\n", cstTime)
	}

	elapsed := time.Since(start) // 程序执行时间
	fmt.Printf("\n程序运行时间: %s\n", elapsed)
}

image.png
其实也想过协程或者其他方式?但是奈何max-keys 最大是1000测试了一下没有太大的提升放弃了…

总结

在这篇博客中,我们学习了如何使用腾讯云 COS Go SDK 查询存储桶中最新的文件信息。这包括如何创建COS客户端,如何逐页检索对象列表,并如何对结果排序以找到最后更新的对象。我们还展示了如何优化用户体验,通过实时进度更新和检索多个文件来改进程序。

希望本文能帮助你在使用腾讯云 COS 时实现更高效的数据管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1476481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

iMazing3安全吗?好不好用?值不值得下载

一、安全性 iMazing在设计和开发过程中,始终把用户数据的安全性放在首位。它采用了多种先进的安全技术来确保用户数据在传输、备份和存储过程中的安全。 iMazing3Mac-最新绿色安装包下载如下: https://wm.makeding.com/iclk/?zoneid49816 iMazing3Wi…

森林监测VR虚拟情景再现系统更便利

AI人工智能技术已经逐渐渗透到各个领域,为我们的生活带来了诸多便利。在虚拟仿真教学领域,AI技术的应用也日益丰富,为虚拟情景交互体验带来了前所未有的好处。 提高VR虚拟情景的逼真度 通过深度学习和计算机视觉等技术,AI/VR虚拟现…

java008 - Java方法

1、方法概述 1.1 概念 将独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集。 1.2 注意事项 方法必须先创建才能使用,该过程称为方法的定义方法创建好不能直接运行,需要手动使用才执行,该过程称为方法的调用 2、方…

基于RISC-V架构的通信DSP的设计以及在5G RedCap基带中的应用(五)-基于RISC-V的RedCap DSP在5G基带中的应用

4 基于RISC-V的RedCap DSP在5G基带中的应用 4.1 基带处理器的关键任务和性能需求 基带处理器是移动通信设备中的关键部件,负责处理无线信号,包括信号的接收、发送和处理。在5G通信系统中,基带处理器的关键任务和性能需求包括以下几个方面&a…

【网站项目】424学报稿件管理系统

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…

面试数据库篇(mysql)- 11主从同步

原理 MySQL主从复制的核心就是二进制日志 二进制日志(BINLOG)记录了所有的 DDL(数据定义语言)语句和 DML(数据操纵语言)语句,但不包括数据查询(SELECT、SHOW)语句。 复…

Vue 2 的核心模块和历史遗留问题以及vue3新特性

从下图你能看到,Vue 2 是一个响应式驱动的、内置虚拟 DOM、组件 化、用在浏览器开发,并且有一个运行时把这些模块很好地管理起来的框架。 vue 2 能把上面所说的这些模块很好地管理起来,看起来已经足够好了。不过事实真的如 此么?…

day01-HTML-CSS

一、Web 开发 1. 什么是 Web ? Web:全球广域网,也称为万维网(www,World Wide Web),能够通过浏览器访问的 网站。 2. Web 网站的开发模式 3. Web 标准 Web 标准也称为网页标准,由一系列的标准组成&#xff…

24计算机考研深大经验分享(计算机专业考研综合安排)

文章目录 背景科目选择高数选课一轮二轮冲刺阶段 线代一轮二轮 概率论计算机学科专业基础408数据结构计算机组成原理操作系统计算机网络总结 英语政治 末言 背景 首先贴一下初试成绩。这篇分享主要是给零基础的同学使用的,基础好的同学可以自行了解补充一下&#xf…

【论文阅读】微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向:综述

Micro and nanobubbles technologies as a new horizon for CO2-EOR and CO2 geological storage techniques: A review 微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向:综述 期刊信息:Fuel 2023 期刊级别:EI检索 SCI升级版工程技术1区…

力扣128. 最长连续序列(哈希表)

Problem: 128. 最长连续序列 文章目录 题目描述思路复杂度Code 题目描述 思路 1.先将数组中的元素存入到一个set集合中(去除重复的元素) 2.欲找出最长连续序列(先定义两个int变量longestSequence和currentSequence用于记录最长连续序列和当前…

redis启动错误

错误: Creating Server TCP listening socket 127.0.0.1:6379: bind: No error redis-server.exe redis.windows.conf redis-cli.exe shutdown auth "yourpassword"

resilience4j 2.0.0版本使用要求最低JDK17(使用踩坑记录)

文章目录 🔊博主介绍🥤本文内容📢文章总结📥博主目标 🔊博主介绍 🌟我是廖志伟,一名Java开发工程师、Java领域优质创作者、CSDN博客专家、51CTO专家博主、阿里云专家博主、清华大学出版社签约作…

Linux笔记--文件权限

一、相关概念 Linux最优秀的地方之一就在于多人多任务环境。为了让各个使用者有较为保密的文件数据,文件的权限管理尤为重要。 ●文件的可存取身份: owner:文件拥有者 group:文件所属用户组 others:其他人 ●文件权限: r: read,读 文件:是否能查看文件内…

动态规划之使用最小花费爬楼梯【LeetCode】

动态规划之使用最小花费爬楼梯 LCR 088. 使用最小花费爬楼梯解法1解法2 LCR 088. 使用最小花费爬楼梯 LCR 088. 使用最小花费爬楼梯 解法1 状态表示(这是最重要的):dp[i]表示以第i级台阶为楼层顶部,到达第i层台阶的最低花费。 状…

性能分析排查思路之日志(1)

本文是性能问题分析排查思路的展开内容之一,主要分为日志1期,机器4期、环境2期共7篇系列文章,本期是第一篇,讲日志的分析方法和经验。 系列文章传送门: 一图梳理性能问题分析排查思路-总体概述(0&#xff…

‘grafana.ini‘ is read only ‘defaults.ini‘ is read only

docker安装grafana 关闭匿名登录情况下的免密登录遇到问题 grafana.ini is read only defaults.ini is read only 参考回答(Grafana.ini giving me the creeps - #2 by bartweemaels - Configuration - Grafana Labs Community Forums) 正确启动脚本 …

HarmonyOS开发云工程与开发云函数

创建函数 您可直接在DevEco Studio创建函数、编写函数业务代码、为函数配置调用触发器。 1.右击“cloudfunctions”目录,选择“New > Cloud Function”。 2.输入函数名称后,点击“OK”。 函数名称仅支持小写英文字母、数字、中划线(-&a…

高性能图表组件LightningChart .NET v11.0发布——增强DPI感知能力

LightningChart完全由GPU加速,并且性能经过优化,可用于实时显示海量数据-超过10亿个数据点。 LightningChart包括广泛的2D,高级3D,Polar,Smith,3D饼/甜甜圈,地理地图和GIS图表以及适用于科学&am…

【从零开始学习重要知识点 | 第一篇】快速了解什么是幂等性以及常见解决方案

前言: 当我们在设计和实现分布式系统时,幂等性是一个非常重要的概念。幂等性可以简单地理解为:对于同一操作,不论执行多少次,产生的影响都是相同的。这个概念在分布式系统中非常重要,因为在这种环境下&…