HOME 首页
SERVICE 服务产品
XINMEITI 新媒体代运营
CASE 服务案例
NEWS 热点资讯
ABOUT 关于我们
CONTACT 联系我们
创意岭
让品牌有温度、有情感
专注品牌策划15年

    golang生成文件快照(golang上传文件)

    发布时间:2023-04-17 19:17:15     稿源: 创意岭    阅读: 99        

    大家好!今天让创意岭的小编来大家介绍下关于golang生成文件快照的问题,以下是小编对此问题的归纳整理,让我们一起来看看吧。

    开始之前先推荐一个非常厉害的Ai人工智能工具,一键生成原创文章、方案、文案、工作计划、工作报告、论文、代码、作文、做题和对话答疑等等

    只需要输入关键词,就能返回你想要的内容,越精准,写出的就越详细,有微信小程序端、在线网页版、PC客户端

    官网:https://ai.de1919.com

    创意岭作为行业内优秀的企业,服务客户遍布全球各地,如需了解SEO相关业务请拨打电话175-8598-2043,或添加微信:1454722008

    本文目录:

    golang生成文件快照(golang上传文件)

    一、golang中bufio包

    一、介绍go标准库中的bufio

    最近用golang写了一个处理文件的脚本,由于其中涉及到了文件读写,开始使用golang中的 io 包,后来发现golang 中提供了一个bufio的包,使用这个包可以大幅提高文件读写的效率,于是在网上搜索同样的文件读写为什么bufio 要比io 的读写更快速呢?根据网上的资料和阅读源码,以下来详细解释下bufio的高效如何实现的。

    bufio 包介绍

    bufio包实现了有缓冲的I/O。它包装一个io.Reader或io.Writer接口对象,创建另一个也实现了该接口,且同时还提供了缓冲和一些文本I/O的帮助函数的对象。

    以上为官方包的介绍,在其中我们能了解到的信息如下:

    bufio 是通过缓冲来提高效率

    简单的说就是,把文件读取进缓冲(内存)之后再读取的时候就可以避免文件系统的io 从而提高速度。同理,在进行写操作时,先把文件写入缓冲(内存),然后由缓冲写入文件系统。看完以上解释有人可能会表示困惑了,直接把 内容->文件 和 内容->缓冲->文件相比, 缓冲区好像没有起到作用嘛。其实缓冲区的设计是为了存储多次的写入,最后一口气把缓冲区内容写入文件。下面会详细解释

    bufio 封装了io.Reader或io.Writer接口对象,并创建另一个也实现了该接口的对象

    io.Reader或io.Writer 接口实现read() 和 write() 方法,对于实现这个接口的对象都是可以使用这两个方法的

    注明:介绍内容来自博主 LiangWenT

    ,原文链接: https://blog.csdn.net/LiangWenT/article/details/78995468 ,在查找资料时,发现这篇博客的内容很好理解

    bufio包实现了缓存IO。它包装了io.Reader和io.Write对象,创建了另外的Reader和Writer对象,它们也实现了io.Reader和io.Write接口,具有缓存。注意:缓存是放在主存中,既然是保存在主存里,断电会丢失数据,那么要及时保存数据。

    二、常用内容

    1、Reader类型

    NewReaderSize

    作用:NewReaderSize将rd封装成一个带缓存的bufio.Reader对象。缓存大小由size指定(如果小于16则会被设为16)。如果rd的基类型就是有足够缓存的bufio.Reader类型,则直接将rd转换为基类型返回。

    NewReader

    funcReader相当于NewReaderSize(rd, 4096)

    Peek

    Peek返回缓存的一个切片,该切片引用缓存中前n个字节的数据,该操作不会将数据读出,只是引用,引用的数据在下一次读取操作之前有效的。如果切片长度小于n,则返回一个错误信息说明原因。如果n大于缓存的总大小,则返回ErrBufferFull。

    Read

    Read从b中数据到p中,返回读出的字节数和遇到的错误。如果缓存不为空,则只能读出缓冲中的数据,不会从底层io.Reader中提取数据,如果缓存为空,则:

    1、len(p) >= 缓存大小,则跳过缓存,直接从底层io.Reader中读出到p中

    2、len(p)< 缓存大小,则先将数据从底层io.Reader中读取到缓存中,再从缓存读取到p中。

    Buffered

    Buffered返回缓存中未读取的数据的长度。

    Discard

    Discard跳过后续的n个字节的数据,返回跳过的字节数。

    Writer类型和方法

    write结构

    NewWriteSize

    NewWriterSize将wr封装成一个带缓存的bufio.Writer对象,缓存大小由size指定(如果小于4096则会被设置未4096)。

    NewWrite

    NewWriter相等于NewWriterSize(wr, 4096)

    WriteString

    WriteString功能同Write,只不过写入的是字符串

    WriteRune

    WriteRune向b写入r的UTF-8编码,返回r的编码长度。

    Flush

    Available

    Available 返回缓存中未使用的空间的长度

    Buffered

    Buffered返回缓存中未提交的数据长度

    Reset

    Reset将b的底层Write重新指定为w,同时丢弃缓存中的所有数据,复位所有标记和错误信息。相当于创建了一个新的bufio.Writer。

    GO中还提供了Scanner类型,处理一些比较简单的场景。如处理按行读取输入序列或空格分隔的词等。

    内容来自: https://blog.csdn.net/wangshubo1989/article/details/70177928

    参考链接:

    1) https://blog.csdn.net/LiangWenT/article/details/78995468

    2) https://blog.csdn.net/wangshubo1989/article/details/70177928

    二、golang命令行库Cobra的使用

    写了2次才写完,内容很长,翻译了很久,内容来源于Cobra github介绍。翻译完也更全面的了解了Cobra,功能相当强大完善,各种使用的场景都考虑到了。另外也扩展了一些其它知识,比如 命令行玩法 , Levenshtein distance 等等。以下是正文:

    Cobra提供简单的接口来创建强大的现代化CLI接口,比如git与go工具。Cobra同时也是一个程序, 用于创建CLI程序

    Cobra是建立在结构的命令、参数和标志之上。

    命令代表操作,参数和标志是这些行动的修饰符。

    最好的应用程序就像读取句子。用户会知道如何使用本机应用程序,因为他们将理解如何使用它。

    比如下面的例子, server 是命令, port 是标志:

    在下面的命令,我们告诉Git克隆url地址bare

    使用Cobra很简单。首先,使用 go get 安装最新版本

    然后在你项目里引用Cobra

    通常基于Cobra的应用程序将遵循下面的组织结构,当然你也可以遵循自己的接口:

    在Cobra应用程序中,通常main.go文件非常空洞。它主要只干一件事:初始化Cobra。

    Cobra提供自己的程序来创建你的程序并且添加你想要的命令。这是最简单的方式把Cobra添加到你的程序里。

    这里 你能找到相关信息

    使用Cobra,需要创建一个空的main.go文件和一个rootCmd文件。你可以选择在合适的地方添加额外的命令。

    Cobra不需要特殊的构造函数。简单的就可以创建你的命令。

    理想情况下你把这个放在在 app/cmd/root.go

    你会另外定义标志和处理配置init()函数。

    比如 cmd/root.go

    你需要在main函数里执行root命令。

    通常main.go文件非常空洞。它主要只干一件事:初始化Cobra。

    其它的命令通常定义在cmd/目录下的自己文件内

    如果你想创建一个version命令,你可以创建cmd/version.go文件,并在文件里这么写:

    标志提供修饰符控制动作命令如何操作

    当标志定义好了,我们需要定义一个变量来关联标志

    '持久'表示每个在那个命令下的命令都将能分配到这个标志。对于全局标志,'持久'的标志绑定在root上。

    Cobra默认只在目标命令上解析标志,父命令忽略任何局部标志。通过打开 Command.TraverseChildren Cobra将会在执行任意目标命令前解析标志

    你同样可以通过 viper 绑定标志:

    在这个例子中,永久的标记 author 被 viper 绑定, 注意 , 当用户没有给 --author 提供值, author 不会被赋值。

    标记默认是可选的,如果你希望当一个标记没有设置时,命令行报错,你可以标记它为必须的

    验证位置参数可以通过 Command 的 Args 字段。

    内置下列验证方法

    一个设置自定义验证的例子

    在下面的例子,我们定义了3个命令。2个在顶级,一个(cmdTimes)是其中一个顶级命令的子命令。在这个例子里,由于没有给 rootCmd 提供 Run ,单独的root是不能运行的,必须要有子命令。

    我们仅为一个命令定义了标记。

    更多关于flags的文档可以在 https://github.com/spf13/pflag 找到

    更完整大型程序的例子, 可以查看 Hugo .

    当你的程序有子命令时,Cobra 会自动给你程序添加help命令。当你运行‘app help’,会调用help命令。另外,help同样支持其它输入命令。例如,你有一个没有任何其它配置的命令叫‘create’,当你调用‘app help create’ Corbra 将会起作用。

    下面的输入是 Cobra 自动生成的。除了命令和标志的定义,其它不再需要。

    help 就跟其它命令一样,并没有特殊的逻辑或行为。事实上,你也可以提供你自己help如果你想的话。

    你能为默认的命令,提供你自己的help命令或模板。使用下面的方法:

    后2个也将适用于任何子命令

    当用户提供无效的标记或命令,Cobra 将会返回 用法 。

    你可能从上面的帮助意识到,默认的帮助将被嵌入到用法里然后作为输出。

    你能提供你自己的用法函数或模板给 Cobra 使用。

    比如帮助,方法和模板都可以重写。

    如果Version字段设置到了根命令,Cobra 会提供了一个顶层 ‘--version’标记。运行带上‘--version’标记的程序,将会按照模板版本信息。模板可以通过 cmd.SetVersionTemplate(s string) 方法修改

    在命令运行前或运行后,再运行方法非常容易。 PersistentPreRun 和 PreRun 方法将会在 Run 之前执行。 PersistentPostRun 和 PostRun 方法将会在 Run 之后执行。 Persistent*Run 方法会被子命令继承,如果它们自己没有定义的话。这些方法将按照下面的属性执行:

    下面的例子,2个命令都使用了上面的特性。当子命令执行的时候,它将执行根命令的 PersistentPreRun ,但不会执行根命令的 PersistentPostRun :

    输出:

    Cobra 会自动输出建议,当遇到“unknown command”错误时。这使得当输入错误时, Cobra 的行为类似 git 命令。例如:

    建议会基于注册的子命令自动生成。使用了 Levenshtein distance 的实现。每一个注册的命令会匹配2个距离(忽略大小写)来提供建议。

    如果你希望在你的命令里,禁用建议或虚弱字符串的距离,使用:

    你可以通过 SuggestFor 来给命令提供明确的名词建议。这个特性允许当字符串不相近,但是意思与你的命令相近,别切你也不想给该命令设置别名。比如:

    Cobra 可以基于子命令,标记,等生成文档。以以下格式:

    Cobra 可以生成一个bash-completion文件。如果你给命令添加更多信息,这些completions可以非常强大和灵活。更多介绍在 Bash Completions 。

    三、golang【新人求助】关于菜鸟教程上 go build的问题

    ls是linux下列出文件和目录的命令,在Windows下的对应命令是dir。

    四、如何Golang开发Android应用

    环境配置好复杂,我不得不唠叨几句。

    需要下载golang1.4rc版,下载ndk,然后编译。 然后用go get 下载gobind这个工具, 然后,将写好的代码用gobind转化下,然后使用特殊的编译命令,将代码编译成.so文件,将生成的相关文件,放到android studio的项目中。然后java代码中,利用jni调用引用的代码。

    ... 好,接着往下看吧。

    环境准备

    一台Linux 64的机器

    一个带有AndroidStudioIDE的开发机器

    因为环境配置实在复杂,所以我们引入的docker。

    docker pull codeskyblue/docker-goandroid

    docker run --rm -ti codeskyblue/docker-goandroid bash

    cd example; echo "view example projects

    docker起来之后,什么就都配置好了,NDK啦,java啦,GO的环境变量了,等等,并且还预装了vim,gradle,tmux,git,syncthing,svn

    开始写代码

    写代码之前,先约定下目录结构

    go的代码都放在src/golib下,编译使用make.bash编译脚本,看下这个文件树

    .

    |-- app.iml

    |-- build.gradle

    |-- libs/armeabi-v7a # go编译生成的so文件

    | `-- libgojni.so

    |-- main.go_tmpl # 一个模板文件,先不用管它

    |-- make.bash # 编译脚本,用来生成.so和Java代码

    `-- src

    |-- golib

    | |-- hi

    | | |-- go_hi�0�2�0�2�0�2 # 自动生成的代码

    | | | `-- go_hi.go

    | | `-- hi.go # 需要编写的代码

    | `-- main.go

    `-- main

    |-- AndroidManifest.xml

    |-- java

    | |-- go # 自动生成的代码

    | | |-- Go.java

    | | |-- Seq.java

    | | `-- hi

    | | `-- Hi.java

    | `-- me/shengxiang/gohello # 主要的逻辑代码

    | `-- MainActivity.java

    `-- res

    我已经写了一个例子,先直接搞下来

    编译下,试试行不行(就算不行问题应该也不大,因为大问题都被我消灭了)

    cd GoHello/app

    ./make.bash

    ../gradlew build

    一切顺利的话在build/outputs/apk下应该可以看到app-debug.apk这个文件。(剧透下,这个文件只有800多K)

    编译好的我放到qiniu上了,可以点击下载看看

    下面可以尝试改改,我抛砖引玉说下

    打开hi.go这个文件

    hi.go的内容,比较简单,我们写Go代码主要就是这部分

    // Package hi provides a function for saying hello.

    package hi

    import "fmt"

    func Hello(name string) {

    fmt.Printf("Hello, %s!\n", name)

    return "(Go)World"

    }

    文件末尾添加下面这行代码

    func Welcome(name string) string {

    return fmt.Sprintf("Welcome %s to the go world", name)

    }

    使用./make.bash重新编译下

    打开MainActivity.java 修改下OnClickListener事件

    button.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    String message = Hi.Welcome("yourname");

    Toast.makeText(MainActivity.this, message, Toast.LENGTH_LONG).show();

    }

    });

    编译运行下,把生成的apk安装到手机上试试。

    原理解读(有兴趣的接着看)

    首先说下gobind这个工具。

    go_hi/go_hi.go这个文件时通过gobind这个工具生成的,用来配合一个简单的程序,生成.so文件

    // go_hi.go

    package go_hi

    import (

    "golang.org/x/mobile/bind/seq"

    "example/hi"

    )

    func proxy_Hello(out, in *seq.Buffer) {

    param_name := in.ReadUTF16()

    hi.Hello(param_name)

    }

    func init() {

    seq.Register("hi", 1, proxy_Hello)

    }

    这个简单的程序内容是这样的

    // main.go

    package main

    import (

    "golang.org/x/mobile/app"

    _ "golang.org/x/mobile/bind/java"

    _ "example/hi/go_hi"

    )

    func main() {

    app.Run(app.Callbacks{})

    }

    src/MyActivity.java文件内容是这样的

    import ...

    import go.Go; // 引入Go这个包

    import go.hi.Hi; // gobind生成的代码

    public class MainActivity extends Activity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    Go.init(getApplicationContext()); // 初始化两个线程

    Hi.Hello("world");

    }

    }

    其中有一句Go.init(...)这里再看go.Go这个包是什么样子的

    public final class Go {

    // init loads libgojni.so and starts the runtime.

    public static void init(Context context) {

    ... 判断该函数是否该执行的代码 -- 省略 --

    System.loadLibrary("gojni"); // gojni需要这句

    new Thread("GoMain") {

    public void run() {

    Go.run(); // run()是一个native方法

    }

    }.start();

    Go.waitForRun(); // 这个也是一个native方法

    // 这部分可以理解为,启动了一个后台线程不断的接收结果到缓存中。

    new Thread("GoReceive") {

    public void run() { Seq.receive(); }

    }.start();

    }

    private static boolean running = false;

    private static native void run();

    private static native void waitForRun();

    }

    MyActivity.java中还有段代码是 Hi.Hello("world");,打开Hi.java路径在src/go/hi/Hi.java,这个文件也是gobind生成的,是用来给java方便的调用.so文件

    // Hi.java

    // File is generated by gobind. Do not edit.

    package go.hi;

    import go.Seq;

    public abstract class Hi {

    private Hi() {} // uninstantiable

    public static void Hello(String name) {

    go.Seq _in = new go.Seq();

    go.Seq _out = new go.Seq();

    _in.writeUTF16(name);

    Seq.send(DESCRIPTOR, CALL_Hello, _in, _out); // 下面接着说

    }

    private static final int CALL_Hello = 1;

    private static final String DESCRIPTOR = "hi";

    }

    Seq.send这部分实际上最终调用的是一段go代码

    func Send(descriptor string, code int, req *C.uint8_t, reqlen C.size_t, res **C.uint8_t, reslen *C.size_t) {

    fn := seq.Registry[descriptor][code]

    in := new(seq.Buffer)

    if reqlen > 0 {

    in.Data = (*[maxSliceLen]byte)(unsafe.Pointer(req))[:reqlen]

    }

    out := new(seq.Buffer)

    fn(out, in)

    seqToBuf(res, reslen, out)

    }

    转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦

    以上就是关于golang生成文件快照相关问题的回答。希望能帮到你,如有更多相关问题,您也可以联系我们的客服进行咨询,客服也会为您讲解更多精彩的知识和内容。


    推荐阅读:

    小智logo在线制作神器

    电视台logo设计(电视台logo设计说明)

    good趣味记忆法(grape趣味记忆法)

    腾讯游戏内测资格怎么获得(腾讯游戏的内测资格怎么获取)

    杭州十大杰出青年名单(杭州十大杰出青年名单公示)