• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Go 操作 数据库、Redis、HDFS

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

楔子

这里我们来介绍一下如何使用 Go 连接数据库、Redis、HDFS,当然数据库、Redis、HDFS本身我们就不介绍了,这里我们主要介绍如何使用 Go 进行连接并执行相应操作。

Go 操作数据库

对于许多Web应用程序而言,数据库都是其核心所在,数据库几乎可以用来存储你想查询和修改的任何信息。

但是Go本身没有内置任何的驱动来操作数据库,但是 Go 内置 database/sql,里面定义了一些接口,用于可以根据接口开发相应数据库的驱动。比如:MySQL、PostgreSQL是不同的数据库,但是我们都可以使用 database/sql 进行操作。常见的数据库驱动如下:

  • Mysql: https://github.com/go-sql-driver/mysql
  • MyMysql: https://github.com/ziutek/mymysql
  • Postgres: https://github.com/lib/pq
  • Tidb: https://github.com/pingcap/tidb
  • SQLite: https://github.com/mattn/go-sqlite3
  • MsSql: https://github.com/denisenkom/go-mssqldb
  • Oracle: https://github.com/mattn/go-oci8

这里我们就使用PostgreSQL进行演示。

连接数据库

要想使用Go操作PostgreSQL,那么首先要和数据库之间建立连接,得到DB对象。

import (
    "database/sql"
    _ "github.com/lib/pq"
)

database/sql 是 Go 的标准库之一,它提供了一系列接口方法,用于访问关系数据库。它并不会提供数据库特有的方法,那些特有的方法会交给具体的数据库驱动去实现。

我们正在加载的驱动是匿名的,导入之后该驱动会自行初始化并注册到 Go 的 database/sql 上下文中,因此我们就可以 database/sql 包提供的方法去访问数据库了。

下面是建立连接,建立连接的话使用 sql.Open 函数:

func Open(driverName, dataSourceName string) (*DB, error) {
    /*
    driverName: 这个名字就是数据库驱动注册到 database/sql 时所使用的名字
    		   如果是MySQL数据库的话, 那么就是"mysql"; 如果是PostgreSQL数据库的话, 那么就是"postgres";
    dataSourceName: 数据库的连接信息, 这个连接包括了数据库的用户名、密码、数据库主机以及连接的数据库名等信息
    			   用户名:密码@协议(地址:端口)/数据库?参数=参数值
    			   
    db, err := sql.Open("postgres", "postgres:zgghyys123@tcp(localhost:5432)/postgres")
    */
}

代码演示一下:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func main() {
    // 这里的open函数只是验证参数是否合法, 不会创建和数据库的连接; 得到的仅仅是一个sql.DB对象, 当进行数据库查询的时候才会建立网络连接
    // sql.DB 表示操作数据库的抽象接口, 但不是所谓的数据库连接对象, 它只有在需要使用时才会创建连接
    // 注意: dataSourceName结尾的 sslmode=disable, 如果没有的话会报错: pq: SSL is not enabled on the server
    db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    // 记得关闭连接, 这里使用defer, 由于该函数返回一个error, 所以我们放在匿名函数中
    defer func() {_ = db.Close()}()

    // 如果要立刻检测数据库源是否能连接到指定的数据库, 需要调用返回值的Ping方法
    fmt.Println(db.Ping()) // <nil>
    // 打印nil证明没有错误
}

接下来就可以进行操作了,不过我们还可以设置连接数:

func (db *DB) SetMaxOpenConns(n int)
// SetMaxOpenConns表示设置与数据库建立连接的最大数目
// 如果n大于0且小于最大闲置连接数, 会将最大闲置连接数减小到和最大开启连接数相等
// 如果n<=0, 不会限制最大开启连接数, 默认为0(无限制)

func (db *DB) SetMaxIdleConns(n int)
// SetMaxIdleConns设置连接池中的最大闲置连接数
// 如果n大于最大开启连接数, 则会将新的最大闲置连接数会减小到和最大开启连接数相等
// 如果n<=0, 不会保留闲置连接

个人觉得这两个设置连接数,基本很少用,使用默认的即可。

增删改查

下面就是喜闻乐见的增删改查环节了,说是增删改查,其实说白了还是体现在sql语句上。Go 的话,则只是一个连接、执行的过程。

查询单条数据:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

type staff struct {
    name string
    status string
    // 由于数据库字段名 type 和 Go 关键字冲突, 所以这里采用首字母大写的形式
    // 首字母大小写无影响
    Type string
    month int64
}
func main() {
    db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer func() {_ = db.Close()}()

    var s staff
    //这里的$1表示占位符
    query := "select * from staff where month = $7"
    //QueryRow查询单条数据
    row := db.QueryRow(query, 7)
    // 调用 row.Scan 将结果赋值给结构体成员
    if err := row.Scan(&s.name, &s.status, &s.Type, &s.month); err != nil {
        panic(err)
    }
    // 注意: 如果查询不到的话, 那么调用Scan会报错, 因此这里错误实际上不应该抛出的
    fmt.Println(row)
}

查询多条数据:

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

type staff struct {
    name string
    status string
    Type string
    month int64
}
func main() {
    db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer func() {_ = db.Close()}()

    var s staff
    query := "select * from staff where month = $1"
    //只需要把QueryRow换成Query就可以了, 但是返回值会多出一个 error
    rows, err := db.Query(query, 7)
    if err != nil {
        panic(err)
    }
    // 然后通过循环直接获取
    for rows.Next() {
        if err := rows.Scan(&s.name, &s.status, &s.Type, &s.month); err != nil {
            panic(err)
        } else {
            fmt.Println(s)
            /*
            {刘秀珍 完成 文件管理 7}
            {王亮 完成 文件管理 7}
            {胡秀华 未完成 文件管理 7}
            {胡秀华 完成 质量安全 7}
            {王亮 完成 文件管理 7}
            {王亮 未完成 班组建设 7}
            {林晨 完成 现场推演 7}
            */
        }
    }
}

除此之外我们在查询的时候还可以获取字段名,以及相应的字段属性。

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer func() {_ = db.Close()}()

    query := "select * from staff where month = $1"
    rows, err := db.Query(query, 7)
    if err != nil {
        panic(err)
    }

    columns, _ := rows.Columns()
    fmt.Println("字段名:", columns)  // 字段名: [name status type month]

    // 还可以获取字段属性
    /*
    column_types, _ := rows.ColumnTypes()
    for _, col_type := range column_types {
        // 可查看的属性可以通过源代码查看
    }
    */
}

插入数据:

插入、更新和删除操作都使用相同的方法。

func (db *DB) Exec(query string, args ...interface{}) (Result, error)

可以直接调用 db.Exec 进行操作。

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer func() {_ = db.Close()}()

    query := "insert into staff(status, month) values ($1, $2)"

    res, err := db.Exec(query, "完成", 8)
    if err != nil {
        panic(err)
    }

    // 返回插入的记录id, 但是报错; 这个driver不支持, 但mysql是支持的
    if id, err := res.LastInsertId(); err!=nil {
        fmt.Println(err)  // LastInsertId is not supported by this driver
    } else {
        fmt.Println(id)
    }

    //返回影响的行数
    if count, err := res.RowsAffected(); err!=nil {
        fmt.Println(err)
    } else {
        fmt.Println(count)  // 1
    }
}

更新数据和删除数据也是同理,这里不赘述了。

预处理

1. 什么是预处理?

普通SQL语句执行过程:

  • 客户端对SQL语句进行占位符替换得到完整的SQL语句

  • 客户端发送完整SQL语句到数据库服务端

  • 数据库服务端执行完整的SQL语句并将结果返回给客户端

预处理执行过程:

  • 把SQL语句分成两部分,命令部分与数据部分

  • 先把命令部分发送给数据库服务端,数据库服务端进行SQL预处理

  • 然后把数据部分发送给数据库服务端,数据库服务端对SQL语句进行占位符替换

  • 数据库服务端执行完整的SQL语句并将结果返回给客户端

2. 为什么要预处理?

1. 优化MySQL服务器重复执行SQL的方法,可以提升服务器性能,提前让服务器编译,一次编译多次执行,节省后续编译的成本。

2. 避免SQL注入问题。

3. Go实现预处理

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer func() {_ = db.Close()}()

    //Prepare方法会先将sql语句发送给数据库服务端, 返回一个准备好的状态用于之后的查询和命令, 返回值可以同时执行多个查询和命令。
    query := "insert into staff(status, month) values ($1, $2)"
    stmt, _ := db.Prepare(query)
    defer func() {_ = stmt.Close()}()

    // 传入参数, 这里就不需要query了, 直接传递占位符对应的值即可
    res, _ := stmt.Exec("未完成", 9)
    count, _ := res.RowsAffected()
    fmt.Println(count)  // 1

    // 当然这里可以执行多次Exec, 传入不同的参数
    res, _ = stmt.Exec("未完成", 10)
    count, _ = res.RowsAffected()
    fmt.Println(count)  // 1
}

Go实现数据库事务

1. 什么是事务?

事务:一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元),同时这个完整的业务需要执行多次的DML(insert、update、delete)语句共同联合完成。A转账给B,这里面就需要执行两次update操作。

在MySQL中只有使用了Innodb数据库引擎的数据库或表才支持事务。事务处理可以用来维护数据库的完整性,保证成批的SQL语句要么全部执行,要么全部不执行。

2. 事务的ACID

通常事务必须满足4个条件(ACID):原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。

3. 事务相关方法

Go语言中使用以下三个方法实现MySQL中的事务操作。

  • 开始事务

     func (db *DB) Begin() (*Tx, error)
    
  • 提交事务

     func (tx *Tx) Commit() error
    
  • 回滚事务

     func (tx *Tx) Rollback() error
    

4. 事务示例

package main

import (
    "database/sql"
    "fmt"
    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgres", "postgres://postgres:[email protected]:5432/postgres?sslmode=disable")
    if err != nil {
        panic(err)
    }
    defer func() {_ = db.Close()}()

    // 开启事务
    tx, err := db.Begin()
    if err != nil {
        panic(err)
    }
    query1 := "insert into staff(status, month) values ($1, $2)"
    tx.Exec(query1, "完成", 9)
    tx.Exec(query1, "未完成", 10)
    tx.Exec(query1, "完成", 11)

    //提交事务
    if err = tx.Commit(); err != nil {
        // 失败了则进行回滚
        tx.Rollback()
        panic(err)
    }  
    fmt.Println("事务完成")  // 事务完成
}

SQL中的占位符

不同的数据库中,SQL语句使用的占位符语法不尽相同。

Go 操作Redis

Go 操作Redis需要使用第三方库,这里我们使用的第三方库是 https://github.com/go-redis/redis,Star数比较高的一个库。

首先是连接,Client对象是和Redis协作的主要接口,可以使用NewClient进行创建。

client := redis.NewClient(&redis.Options{
        Addr:     "47.94.174.89:6379",
        Password: "", // 无密码
        DB:       0,  // 使用 0 号数据库
    })

有了 client,那么便可以对Redis进行操作了,里面定义了大量的方法,和Redis命令是对应的。熟悉Redis的话,那么看源码以及注释完全可以直接上手操作。

package main

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

func main() {
    client := redis.NewClient(&redis.Options{
        Addr:     "xx.xx.xx.xx:6379",
        Password: "", // 无密码
        DB:       0,  // 使用 0 号数据库
    })
    ctx := context.Background()

    client.Set(ctx, "name", "夏色祭", 0)
    val, err := client.Get(ctx, "name").Result()
    // 如果key不存在的话, 那么err == redis.Nil
    if err != redis.Nil {
        fmt.Println(val)  // 夏色祭
    }
}

这里可以自己尝试操作一下,不再赘述了,比较简单。因为Redis本身比较简单,而且Go提供的API和Redis命令之间也是具有很高的相似度的。

Go 操作HDFS

HDFS指的是Hadoop的分布式文件存储系统,Go 也是可以对其进行操作的,我们来看一下。

首先是安装操作HDFS的第三方库,直接go get github.com/vladimirvivien/gowfs即可

读取文件

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
    "io/ioutil"
)

func main() {
    //这是配置,传入Addr: "ip: 50070", User: "随便写一个英文名就行"
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    //返回一个客户端(这里面叫文件系统)和error
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:",err))
    }

    //这里不能直接传入文件名,而是需要作为gowfs.Path结构体的Name参数的值
    //然后将Path传进去,我们后面的api都是这样做的
    path := gowfs.Path{Name:"/whitealbum.txt"}

    //接收如下参数:gowfs.Path,offset(偏移量),长度(显然是字节的长度), 容量(自己的cap)
    //返回一个io.ReadCloser,这是需要实现io.Reader和io.Closer的接口
    reader, _ := client.Open(path, 0, 512, 2048)

    //可以使用reader.Read(buf)的方式循环读取,也可以丢给ioutil。ReadAll,一次性全部读取
    data, _ := ioutil.ReadAll(reader)
    fmt.Println(string(data))
    /*
    	白色相簿什么的,已经无所谓了。
    	因为已经不再有歌,值得去唱了。
    	传达不了的恋情,已经不需要了。
    	因为已经不再有人,值得去爱了。
    */
}

查看目录有哪些内容

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    path := gowfs.Path{Name: "/"}
    // 返回[]FileStatus和error
    //这个FileStatus是什么?我们看一下源码
    /*
    	type FileStatus struct {
    		AccesTime        int64  访问时间
    		BlockSize        int64  块大小,只针对文件(134217728 Bytes,128 MB),目录的话为0
    		Group            string 所属组
    		Length           int64  文件的字节数(目录为0)
    		ModificationTime int64  修改时间
    		Owner            string 所有者
    		PathSuffix       string 文件后缀,说白了就是文件名
    		Permission       string 权限
    		Replication      int64  副本数
    		Type             string 类型,文本的话是FILE,目录的话是DIRECTORY
    	}
    */
    fs_arr, _ := client.ListStatus(path)
    fmt.Println(fs_arr)
    // [{0 0 supergroup 0 1570359570447 dr.who tkinter 755 0 DIRECTORY} {0 134217728 supergroup 184 1570359155457 root whitealbum.txt 644 1 FILE}]

    for _, fs := range fs_arr {
        fmt.Println("文件名:", fs.PathSuffix)
        /*
        	文件名: tkinter
        	文件名: whitealbum.txt
        */
    }

    //FileStatus里面包含了文件的详细信息,如果想查看某个文件的详细信息
    //可以使用fs, err := client.GetFileStatus(path)
}

创建文件

package main

import (
    "bytes"
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    path := gowfs.Path{Name: "/黑色相簿.txt"}

    /*
    	Create函数接收如下参数。
    	data:io.Reader,一个实现了io.Reader接口的struct
    	Path:很简单,就是我们这里的path
    	overwrite:是否覆盖,如果为false表示不覆盖,那么要求文件不能存在,否则报错
    	blocksize:块大小
    	replication:副本
    	permission:权限
    	buffersize:缓存大小
    	contenttype:内容类型

    	返回一个bool和error
    */
    if flag, err :=client.Create(
        bytes.NewBufferString("这是黑色相簿,不是白色相簿"), //如果不指定内容,就直接bytes.NewBufferString()即可
        path, //路径
        false,//不覆盖
        0,
        0,
        0666,
        0,
        "text/html",  //纯文本格式
    ); err != nil {
        fmt.Println("创建文件出错,错误为:", err)
    } else {
        fmt.Println("创建文件成功, flag =", flag)  //创建文件成功, flag = true
    }
}

查看一下

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
    "io/ioutil"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    path := gowfs.Path{Name: "/黑色相簿.txt"}

    reader , _ := client.Open(path, 0, 512, 2048)
    data, _ := ioutil.ReadAll(reader)
    fmt.Println(string(data)) // 这是黑色相簿,不是白色相簿
}

创建目录

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    path := gowfs.Path{Name: "/a/b/c"}

    //递归创建
    flag, err := client.MkDirs(path, 0666)
    fmt.Println(flag) // true

    fs_arr, _ := client.ListStatus(gowfs.Path{Name:"/"})
    for _, fs := range fs_arr{
        fmt.Println(fs.PathSuffix)
        /*
        	黑色相簿.txt
        	a
        	tkinter
        	whitealbum.txt
        */
    }
}

重命名

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    fs_arr, _ := client.ListStatus(gowfs.Path{Name:"/"})
    for _, fs := range fs_arr{
        fmt.Println(fs.PathSuffix)
        /*
        	黑色相簿.txt
        	a
        	tkinter
        	whitealbum.txt
        */
    }

    flag, err := client.Rename(gowfs.Path{Name:"/黑色相簿.txt"}, gowfs.Path{Name:"/blackalbum.txt"})
    fmt.Println(flag) // true
    fs_arr, _ = client.ListStatus(gowfs.Path{Name:"/"})
    for _, fs := range fs_arr{
        fmt.Println(fs.PathSuffix)
        /*
        	a
        	blackalbum.txt
        	tkinter
        	whitealbum.txt
        */
    }
}

向已经存在的文件追加内容

package main

import (
    "bytes"
    "fmt"
    "github.com/vladimirvivien/gowfs"
    "io/ioutil"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    path := gowfs.Path{Name: "/whitealbum.txt"}
    reader, _ := client.Open(path, 0, 512, 2048)
    data, _ := ioutil.ReadAll(reader)
    fmt.Println(string(data))
    /*
    	白色相簿什么的,已经无所谓了。
    	因为已经不再有歌,值得去唱了。
    	传达不了的恋情,已经不需要了。
    	因为已经不再有人,值得去爱了。
    */

    //参数1:内容,必须是实现了io.Reader接口
    //参数2:路径
    //参数3:缓存大小
    flag, err := client.Append(bytes.NewBufferString("\n让人讨厌的冬天又来了"), path, 2048)
    fmt.Println(flag) // true

    reader, _ = client.Open(path, 0, 512, 2048)
    data, _ = ioutil.ReadAll(reader)
    fmt.Println(string(data))
    /*
    	白色相簿什么的,已经无所谓了。
    	因为已经不再有歌,值得去唱了。
    	传达不了的恋情,已经不需要了。
    	因为已经不再有人,值得去爱了。

    	让人讨厌的冬天又来了。
    */
}

设置文件或目录的所有者

func (fs *FileSystem) SetOwner(path Path, owner string, group string) (bool, error)

设置文件或目录的权限

func (fs *FileSystem) SetPermission(path Path, permission os.FileMode) (bool, error)

设置文件或目录的副本系数

func (fs *FileSystem) SetReplication(path Path, replication uint16) (bool, error)

设置文件或目录的访问时间和修改时间

func (fs *FileSystem) SetTimes(path Path, accesstime int64, modificationtime int64) (bool, error)

获取文件的校验和

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    path := gowfs.Path{Name: "/whitealbum.txt"}
    f, _ := client.GetFileChecksum(path)
    fmt.Println(f)  // {MD5-of-0MD5-of-512CRC32C 0000020000000000000000001255073187d3e801940eee180acebe4e00000000 28}
    fmt.Println(f.Algorithm, f.Length, f.Bytes) // MD5-of-0MD5-of-512CRC32C 28 0000020000000000000000001255073187d3e801940eee180acebe4e00000000
}

删除文件

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    path := gowfs.Path{Name:"/blackalbum.txt"}
    //路径,是否递归
    flag, _ := client.Delete(path, true)
    fmt.Println(flag) // true
}

判断文件是否存在

为什么这里用蓝色了,因为之后的用法就不一样了

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, err := gowfs.NewFileSystem(config)
    if err != nil {
        panic(fmt.Sprintln("出现异常,异常信息为:", err))
    }

    //创建一个shell,可以使用下面shell进行操作
    shell := gowfs.FsShell{FileSystem: client}

    //直接传字符串即可,不需要传Path了
    flag, _ := shell.Exists("/whitealbum.txt")
    fmt.Println(flag) // true
    flag, _ = shell.Exists("/whitealbum.txt1")
    fmt.Println(flag) // false
}

改变所有者

flag, _ := shell.Chown([]string{"/file1", "/file2", "/file3"}, "owner")

改变所属组

flag, _ := shell.Chgrp([]string{"/file1", "/file2", "/file3"}, "groupName")

改变权限

flag, _ := shell.Chmod([]string{"/file1", "/file2", "/file3"}, 0666)

查看文件内容

package main

import (
    "bytes"
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, _ := gowfs.NewFileSystem(config)

    shell := gowfs.FsShell{FileSystem: client}

    buf := bytes.Buffer{}
    if err := shell.Cat([]string{"/whitealbum.txt"}, &buf); err != nil {
        fmt.Println("err =", err)
    } else {
        fmt.Println(buf.String())
        /*
        	白色相簿什么的,已经无所谓了。
        	因为已经不再有歌,值得去唱了。
        	传达不了的恋情,已经不需要了。
        	因为已经不再有人,值得去爱了。

        	让人讨厌的冬天又来了
        */
    }
}

追加文件内容

package main

import (
    "bytes"
    "fmt"
    "github.com/vladimirvivien/gowfs"
    "io/ioutil"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, _ := gowfs.NewFileSystem(config)

    shell := gowfs.FsShell{FileSystem: client}

    _ = ioutil.WriteFile("aaa.txt", []byte("\n冬马小三\n"), 0666)
    _ = ioutil.WriteFile("bbb.txt", []byte("雪菜碧池\n"), 0666)
    _ = ioutil.WriteFile("ccc.txt", []byte("打死春哥\n"), 0666)
    _ = ioutil.WriteFile("ddd.txt", []byte("抱走冬马雪菜"), 0666)

    _, _ = shell.AppendToFile([]string{"aaa.txt", "bbb.txt", "ccc.txt", "ddd.txt"}, "/whitealbum.txt")

    buf := bytes.Buffer{}
    _ = shell.Cat([]string{"/whitealbum.txt"}, &buf)
    fmt.Println(buf.String())
    /*
    	白色相簿什么的,已经无所谓了。
    	因为已经不再有歌,值得去唱了。
    	传达不了的恋情,已经不需要了。
    	因为已经不再有人,值得去爱了。

    	让人讨厌的冬天又来了
    	冬马小三
    	雪菜碧池
    	打死春哥
    	抱走冬马雪菜
    */
}

上传文件

package main

import (
    "fmt"
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, _ := gowfs.NewFileSystem(config)

    shell := gowfs.FsShell{FileSystem: client}

    //本地路径,hdfs路径,是否重写
    _, _ = shell.Put("aaa.txt", "/aaa.txt", false)

    path := gowfs.Path{Name: "/"}
    fs_arr, _ := client.ListStatus(path)
    for _, fs := range fs_arr {
        fmt.Println(fs.PathSuffix)
        /*
        	黑色相簿.txt
        	a
        	aaa.txt
        	tkinter
        	whitealbum.txt
        */
    }
}

下载文件

package main

import (
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, _ := gowfs.NewFileSystem(config)

    shell := gowfs.FsShell{FileSystem: client}

    _, _ = shell.Get("/whitealbum.txt", "白色album.txt")
}

删除文件

package main

import (
    "github.com/vladimirvivien/gowfs"
)

func main() {
    config := gowfs.Configuration{Addr: "xx.xx.xx.xx:50070", User: "satori"}
    client, _ := gowfs.NewFileSystem(config)

    shell := gowfs.FsShell{FileSystem: client}

    _, _ = shell.Rm("/whitealbum.txt")
}

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
[日常]Go语言圣经-Panic异常,Recover捕获异常习题发布时间:2022-07-10
下一篇:
4.1Goif-else发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap