新闻中心
Go语言实现跨平台获取磁盘空间信息

本文详细介绍了如何使用go语言在不同操作系统(linux/macos和windows)下获取磁盘的可用空间和总空间信息。通过`golang.org/x/sys/unix`和`golang.org/x/sys/windows`包,提供了针对posix和windows系统的具体实现代码,并探讨了如何利用go的构建约束机制来构建一个跨平台的解决方案,帮助开发者便捷地获取类似于`df -h`的磁盘使用报告。
在开发跨平台应用程序时,获取系统磁盘的可用空间和总空间信息是一个常见的需求,类似于在Linux/macOS上执行df -h命令。Go语言本身的标准库并未直接提供一个统一的跨平台API来完成此任务,但通过利用特定操作系统的系统调用包,我们可以实现这一功能。
1. 在POSIX系统(Linux/macOS)上获取磁盘空间
对于基于POSIX标准的系统,如Linux和macOS,我们可以使用golang.org/x/sys/unix包中的Statfs函数来获取文件系统统计信息。这个函数会填充一个Statfs_t结构体,其中包含了我们所需的大部分磁盘信息。
Statfs_t结构体中的关键字段包括:
- Bsize:文件系统块的大小(字节)。
- Blocks:文件系统中的总块数。
- Bfree:文件系统中可用块的总数(包括为超级用户保留的块)。
- B*ail:非超级用户可用的块数。
通常,我们关注的是非超级用户可用的空间,即B*ail。
以下是一个获取当前工作目录所在文件系统可用空间(字节)的示例:
package main
import (
"fmt"
"log"
"os"
"golang.org/x/sys/unix"
)
func main() {
var stat unix.Statfs_t
// 获取当前工作目录
wd, err := os.Getwd()
if err != nil {
log.Fatalf("获取当前工作目录失败: %v", err)
}
// 调用Statfs获取文件系统信息
err = unix.Statfs(wd, &stat)
if err != nil {
log.Fatalf("调用Statfs失败: %v", err)
}
// 计算可用空间:非超级用户可用块数 * 每块大小
*ailableSpaceBytes := stat.B*ail * uint64(stat.Bsize)
// 计算总空间:总块数 * 每块大小
totalSpaceBytes := stat.Blocks * uint64(stat.Bsize)
// 计算已用空间
usedSpaceBytes := totalSpaceBytes - (stat.Bfree * uint64(stat.Bsize)) // Bfree 是所有可用块,包含root保留的
fmt.Printf("路径: %s
", wd)
fmt.Printf("总空间: %d 字节 (%.2f GB)
", totalSpaceBytes, float64(totalSpaceBytes)/(1024*1024*1024))
fmt.Printf("可用空间: %d 字节 (%.2f GB)
", *ailableSpaceBytes, float64(*ailableSpaceBytes)/(1024*1024*1024))
fmt.Printf("已用空间: %d 字节 (%.2f GB)
", usedSpaceBytes, float64(usedSpaceBytes)/(1024*1024*1024))
}注意事项:
千鹿Pr助手
智能Pr插件,融入众多AI功能和海量素材
128
查看详情
- golang.org/x/sys/unix是一个外部包,需要通过go get golang.org/x/sys/unix进行安装。
- B*ail是针对非root用户可用的空间,这通常是用户最关心的“可用”空间。
2. 在Windows系统上获取磁盘空间
在Windows平台上,我们需要使用golang.org/x/sys/windows包中的GetDiskFreeSpaceEx函数。这个函数能够提供指定驱动器的可用字节数、总字节数以及总的可用字节数。
GetDiskFreeSpaceEx函数的签名如下: func GetDiskFreeSpaceEx(lpDirectoryName *uint16, lpFreeBytesAvailable *uint64, lpTotalNumberOfBytes *uint64, lpTotalNumberOfFreeBytes *uint64) (err error)
参数说明:
- lpDirectoryName:指向一个以null结尾的字符串,指定要获取信息的磁盘或UNC路径。例如,"C:"。在Go中,需要将其转换为UTF16指针。
- lpFreeBytesAvailable:接收调用用户可用的字节数。
- lpTotalNumberOfBytes:接收磁盘的总字节数。
- lpTotalNumberOfFreeBytes:接收磁盘上所有用户可用的总字节数。
以下是一个获取C盘磁盘空间信息的示例:
package main
import (
"fmt"
"log"
"syscall"
"golang.org/x/sys/windows"
)
func main() {
var freeBytesAvailable uint64
var totalNumberOfBytes uint64
var totalNumberOfFreeBytes uint64 // 所有用户可用的总字节数
// 指定要查询的驱动器路径,并转换为UTF16指针
drive := "C:\"
drivePtr, err := syscall.UTF16PtrFromString(drive)
if err != nil {
log.Fatalf("转换驱动器路径失败: %v", err)
}
// 调用GetDiskFreeSpaceEx
err = windows.GetDiskFreeSpaceEx(drivePtr,
&freeBytesAvailable, // 当前用户可用的字节数
&totalNumberOfBytes, // 磁盘总字节数
&totalNumberOfFreeBytes) // 磁盘上所有用户可用的总字节数
if err != nil {
log.Fatalf("调用GetDiskFreeSpaceEx失败: %v", err)
}
fmt.Printf("驱动器: %s
", drive)
fmt.Printf("总空间: %d 字节 (%.2f GB)
", totalNumberOfBytes, float64(totalNumberOfBytes)/(1024*1024*1024))
fmt.Printf("当前用户可用空间: %d 字节 (%.2f GB)
", freeBytesAvailable, float64(freeBytesAvailable)/(1024*1024*1024))
fmt.Printf("所有用户可用空间: %d 字节 (%.2f GB)
", totalNumberOfFreeBytes, float64(totalNumberOfFreeBytes)/(1024*1024*1024))
fmt.Printf("已用空间: %d 字节 (%.2f GB)
", totalNumberOfBytes-totalNumberOfFreeBytes, float64(totalNumberOfBytes-totalNumberOfFreeBytes)/(1024*1024*1024))
}注意事项:
- golang.org/x/sys/windows是一个外部包,需要通过go get golang.org/x/sys/windows进行安装。
- syscall.UTF16PtrFromString用于将Go字符串转换为Windows API所需的UTF16指针。
3. 构建跨平台的磁盘空间获取功能
为了实现一个统一的跨平台API来获取磁盘空间,我们可以利用Go语言的构建约束(Build Constraints)机制。通过在文件名或文件顶部添加特定的注释,Go编译器会根据目标操作系统选择性地编译不同的源文件。
构建约束示例:
- //go:build windows:仅在Windows系统上编译。
- //go:build unix:仅在类Unix系统(Linux, macOS, FreeBSD等)上编译。
我们可以创建一个公共接口(例如,一个名为DiskUsage的结构体或函数),然后为每个操作系统提供一个具体的实现文件。
示例文件结构:
disk_usage/ ├── disk_usage.go // 定义公共接口和结构体 ├── disk_usage_unix.go // Unix/Linux/macOS 实现 └── disk_usage_windows.go // Windows 实现
disk_usage.go (公共接口定义):
package disk_usage
import "fmt"
// DiskStatus 存储磁盘使用情况信息
type DiskStatus struct {
Total uint64 // 总空间 (字节)
Free uint64 // 可用空间 (字节)
Used uint64 // 已用空间 (字节)
FreeForUser uint64 // 对当前用户可用的空间 (字节)
}
// GetDiskUsage 获取指定路径的磁盘使用情况
// 此函数将在不同的操作系统中被具体实现
func GetDiskUsage(path string) (*DiskStatus, error) {
// 这是一个占位符,实际实现将在特定OS文件中
return nil, fmt.Errorf("未实现GetDiskUsage函数")
}disk_usage_unix.go (Unix系统实现):
//go:build unix
package disk_usage
import (
"fmt"
"golang.org/x/sys/unix"
)
func GetDiskUsage(path string) (*DiskStatus, error) {
var stat unix.Statfs_t
err := unix.Statfs(path, &stat)
if err != nil {
return nil, fmt.Errorf("获取Unix磁盘状态失败: %w", err)
}
total := stat.Blocks * uint64(stat.Bsize)
free := stat.Bfree * uint64(stat.Bsize) // 包括root保留的
freeForUser := stat.B*ail * uint64(stat.Bsize)
used := total - free // 粗略计算,可能不完全精确,因为文件系统开销
return &DiskStatus{
Total: total,
Free: free,
Used: used,
FreeForUser: freeForUser,
}, nil
}disk_usage_windows.go (Windows系统实现):
//go:build windows
package disk_usage
import (
"fmt"
"syscall"
"golang.org/x/sys/windows"
)
func GetDiskUsage(path string) (*DiskStatus, error) {
var freeBytesAvailable uint64
var totalNumberOfBytes uint64
var totalNumberOfFreeBytes uint64
// Windows路径需要以反斜杠结尾,例如 "C:"
if len(path) > 0 && path[len(path)-1] != '\' {
path += "\"
}
drivePtr, err := syscall.UTF16PtrFromString(path)
if err != nil {
return nil, fmt.Errorf("转换Windows驱动器路径失败: %w", err)
}
err = windows.GetDiskFreeSpaceEx(drivePtr,
&freeBytesAvailable,
&totalNumberOfBytes,
&totalNumberOfFreeBytes)
if err != nil
{
return nil, fmt.Errorf("获取Windows磁盘状态失败: %w", err)
}
used := totalNumberOfBytes - totalNumberOfFreeBytes
return &DiskStatus{
Total: totalNumberOfBytes,
Free: totalNumberOfFreeBytes, // 所有用户可用的总字节数
Used: used,
FreeForUser: freeBytesAvailable, // 当前用户可用的字节数
}, nil
}通过这种方式,当你在不同的操作系统上编译你的Go程序时,Go工具链会自动选择正确的disk_usage_*.go文件进行编译,从而提供一个统一的GetDiskUsage函数接口。
总结
Go语言虽然没有提供一个开箱即用的跨平台API来获取磁盘空间信息,但通过利用其强大的golang.org/x/sys系列包和灵活的构建约束机制,我们可以轻松地为不同操作系统编写特定的实现,并将其封装成一个统一的、易于使用的跨平台功能。这不仅提高了代码的可维护性,也使得Go程序能够更好地适应多样化的运行环境。对于更复杂的磁盘操作,可以考虑使用或参考已有的开源库,例如在问题描述中提到的github.com/ricochet2200/go-disk-usage,它已经实现了这种跨平台逻辑。
以上就是Go语言实现跨平台获取磁盘空间信息的详细内容,更多请关注其它相关文章!
# 提供一个
# 泰安有名seo策略
# 朔州seo优化
# 阜阳抖音seo技术招聘
# 旅游线路推广营销案例
# 沈河区网站建设优化价格
# 丑小鸭教案网站建设文案
# 上海苹果关键词排名优化
# 如何做好内链seo
# 台北谁懂做关键词排名
# 洪泽seo网站优化推广价格
# 我们可以
# 所需
# 将在
# 转换为
# 已用
# linux
# 文件系统
# 磁盘空间
# 是一个
# ai
# mac
# c盘
# 工具
# 字节
# go语言
# 操作系统
# golang
# github
# windows
# go
# git
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
漫蛙2在线漫画入口 漫蛙正版漫画网页版直达
Yandex免登录官网入口_俄罗斯Yandex搜索引擎直达链接
快手赚钱渠道_快手收益来源
c++ 命名空间怎么用 c++ namespace使用指南
从J*aScript对象中精确提取指定属性的教程
AO3同人作品网入口 AO3搜索引擎官网永久地址
《刺客信条4:黑旗》重制版新细节曝光:无缝加载 地图更细致!
c++ 获取系统当前时间 c++时间戳获取方法
QQ邮箱网页版入口 QQ邮箱官方邮箱登录通道
LINUX下如何进行磁盘分区_fdisk与parted工具在LINUX中的使用对比
TypeScript/J*aScript:高效查找数组中首个唯一ID对象
服务端验证_j*ascript输入检查
漫蛙2(台版)官方入口地址 漫蛙2(台版)正版漫画网页端
EMS快递官网app_中国邮政速递物流手机客户端
AO3官方在线访问地址 Archive of Our Own最新镜像合集
深入理解字体排版:Adobe光学字偶距与CSS字偶距的差异与实现
c++如何使用std::memory_order控制原子操作顺序_c++ C++11内存模型详解
C++如何检测键盘输入_C++ _kbhit与_getch函数非阻塞输入
消息称三星明年 2 月正式发布 HBM4,与 SK 海力士同台竞技
在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案
mcjs网页版在线存档 mcjs云存档登录入口
抖音隐秘迷城小游戏入口_ 抖音冒险解谜小游戏秒玩
漫蛙漫画网页端入口 漫蛙2官方正版漫画站点
Win11截图该按哪些键 Win11截屏完整流程解析【教程】
荣耀Play7TPro怎样在信息App置顶客服对话_iPhone荣耀Play7TPro信息App置顶客服对话【优先查看】
Windows 11怎么彻底关闭定位_Windows 11服务中禁用Geolocation
构建轻量级网站内部消息系统:Formspree 集成指南
taptap防沉迷怎么解除 taptap解除健康系统限制说明【2025最新】
Go语言中的*string:深入理解字符串指针
怎么去除衣服上的口红印_生活小妙招教你用酒精轻松擦除
Win11怎么设置鼠标指针速度_Win11提高鼠标指针精确度选项
Archive of Our Own官网直达 AO3最新可用地址一览
Django表单验证失败时保留用户输入数据的最佳实践
Lar*el头像管理:图片缩放与旧文件删除的最佳实践
Safari怎么安装扩展程序 浏览器插件安装与管理方法【详解】
谷歌浏览器如何快速清除某个网站的数据_Chrome网站缓存清理方法
内存疯狂猛猛涨价:主板销量直接腰斩!
必由学在线入口 必由学网页版快速登录入口
J*aScript动态修改指定div内所有a标签样式指南
文心一言怎样用插件调度API数据_文心一言用插件调度API数据【API调用】
mysql备份恢复性能优化_mysql备份恢复性能优化方法
J*a中实现Go语言select通道多路复用机制
c++中的std::basic_string的SSO优化_c++短字符串优化深度解析
漫蛙漫画官方首页 漫蛙2漫画在线阅读入口
微信网页版登录教程_微信网页版登录入口在哪
QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台
小米汽车11月交付量突破40000台!雷军:将继续努力
拼多多购物车商品数量无法修改如何处理 拼多多购物车操作优化方法
PHP URL参数传递与500错误调试指南
ArrayList与LinkedList操作复杂度详解:遍历与修改


2025-11-10
浏览次数:次
返回列表
{
return nil, fmt.Errorf("获取Windows磁盘状态失败: %w", err)
}
used := totalNumberOfBytes - totalNumberOfFreeBytes
return &DiskStatus{
Total: totalNumberOfBytes,
Free: totalNumberOfFreeBytes, // 所有用户可用的总字节数
Used: used,
FreeForUser: freeBytesAvailable, // 当前用户可用的字节数
}, nil
}