在Go中处理SMB2的*RemoteFileSystem时,你看到的是结构体指针的内存地址。以下是具体的使用方法:
1. 直接使用filesystem变量
你获取的filesystem已经是*RemoteFileSystem类型,可以直接调用其方法:
package main
import (
"fmt"
"github.com/hirochachacha/go-smb2"
"net"
)
func main() {
conn, err := net.Dial("tcp", "server:445")
if err != nil {
panic(err)
}
defer conn.Close()
d := &smb2.Dialer{
Initiator: &smb2.NTLMInitiator{
User: "username",
Password: "password",
},
}
client, err := d.Dial(conn)
if err != nil {
panic(err)
}
defer client.Logoff()
// 获取RemoteFileSystem指针
filesystem, err := client.Mount("sharename")
if err != nil {
panic(err)
}
defer filesystem.Umount()
// 直接使用filesystem调用方法
// 列出目录
entries, err := filesystem.ReadDir(".")
if err != nil {
panic(err)
}
for _, entry := range entries {
fmt.Println(entry.Name())
}
// 删除文件
err = filesystem.Remove("test.txt")
if err != nil {
fmt.Println("删除失败:", err)
}
// 读取文件
f, err := filesystem.Open("document.pdf")
if err != nil {
panic(err)
}
defer f.Close()
buf := make([]byte, 1024)
n, err := f.Read(buf)
if err != nil {
panic(err)
}
fmt.Printf("读取了 %d 字节\n", n)
}
2. 将filesystem传递给其他函数
package main
import (
"fmt"
"github.com/hirochachacha/go-smb2"
"io"
"net"
)
// 接受*RemoteFileSystem作为参数的函数
func listFiles(fs *smb2.RemoteFileSystem, path string) error {
entries, err := fs.ReadDir(path)
if err != nil {
return err
}
for _, entry := range entries {
fmt.Printf("%s (目录: %v)\n", entry.Name(), entry.IsDir())
}
return nil
}
// 另一个使用filesystem的函数
func copyFile(fs *smb2.RemoteFileSystem, src, dst string) error {
srcFile, err := fs.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
dstFile, err := fs.Create(dst)
if err != nil {
return err
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
return err
}
func main() {
// ... 连接和认证代码同上
filesystem, err := client.Mount("sharename")
if err != nil {
panic(err)
}
defer filesystem.Umount()
// 将filesystem传递给其他函数
fmt.Println("目录列表:")
if err := listFiles(filesystem, "."); err != nil {
panic(err)
}
fmt.Println("\n复制文件:")
if err := copyFile(filesystem, "source.txt", "destination.txt"); err != nil {
panic(err)
}
}
3. 关于 * 和 & 的解释
// * 表示指针类型
var fs *RemoteFileSystem // fs是一个指向RemoteFileSystem的指针
// & 获取变量的地址(创建指针)
var value int = 42
var ptr *int = &value // ptr现在指向value的内存地址
// 对于结构体
type RemoteFileSystem struct {
client *Client
share string
}
// 创建实例并获取指针的两种方式:
// 方式1:使用new()
fs1 := new(RemoteFileSystem) // fs1是*RemoteFileSystem类型
// 方式2:使用结构体字面量和&
fs2 := &RemoteFileSystem{ // fs2也是*RemoteFileSystem类型
client: someClient,
share: "sharename",
}
// 当你调用client.Mount()时,它返回的就是&RemoteFileSystem{...}
4. 实际使用示例:完整的文件操作
func performFileOperations(fs *smb2.RemoteFileSystem) {
// 创建目录
err := fs.Mkdir("newfolder", 0755)
if err != nil {
fmt.Println("创建目录失败:", err)
}
// 创建并写入文件
file, err := fs.Create("newfolder/test.txt")
if err != nil {
panic(err)
}
_, err = file.Write([]byte("Hello SMB2!"))
if err != nil {
panic(err)
}
file.Close()
// 重命名文件
err = fs.Rename("newfolder/test.txt", "newfolder/renamed.txt")
if err != nil {
panic(err)
}
// 获取文件信息
info, err := fs.Stat("newfolder/renamed.txt")
if err != nil {
panic(err)
}
fmt.Printf("文件大小: %d 字节\n", info.Size())
}
// 在主函数中调用
func main() {
// ... 建立连接和认证
filesystem, err := client.Mount("sharename")
if err != nil {
panic(err)
}
defer filesystem.Umount()
// 直接使用filesystem
performFileOperations(filesystem)
}
你看到的&{0xc000048650 0xc0000160d8}是结构体指针的默认字符串表示,显示的是两个字段的内存地址。在实际使用中,你不需要直接操作这些地址值,只需要使用filesystem变量来调用SMB2提供的方法即可。