HOME 首頁(yè)
SERVICE 服務(wù)產(chǎn)品
XINMEITI 新媒體代運(yùn)營(yíng)
CASE 服務(wù)案例
NEWS 熱點(diǎn)資訊
ABOUT 關(guān)于我們
CONTACT 聯(lián)系我們
創(chuàng)意嶺
讓品牌有溫度、有情感
專注品牌策劃15年

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

    發(fā)布時(shí)間:2023-04-17 19:17:15     稿源: 創(chuàng)意嶺    閱讀: 99        

    大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關(guān)于golang生成文件快照的問題,以下是小編對(duì)此問題的歸納整理,讓我們一起來看看吧。

    開始之前先推薦一個(gè)非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計(jì)劃、工作報(bào)告、論文、代碼、作文、做題和對(duì)話答疑等等

    只需要輸入關(guān)鍵詞,就能返回你想要的內(nèi)容,越精準(zhǔn),寫出的就越詳細(xì),有微信小程序端、在線網(wǎng)頁(yè)版、PC客戶端

    官網(wǎng):https://ai.de1919.com

    創(chuàng)意嶺作為行業(yè)內(nèi)優(yōu)秀的企業(yè),服務(wù)客戶遍布全球各地,如需了解SEO相關(guān)業(yè)務(wù)請(qǐng)撥打電話175-8598-2043,或添加微信:1454722008

    本文目錄:

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

    一、golang中bufio包

    一、介紹go標(biāo)準(zhǔn)庫(kù)中的bufio

    最近用golang寫了一個(gè)處理文件的腳本,由于其中涉及到了文件讀寫,開始使用golang中的 io 包,后來發(fā)現(xiàn)golang 中提供了一個(gè)bufio的包,使用這個(gè)包可以大幅提高文件讀寫的效率,于是在網(wǎng)上搜索同樣的文件讀寫為什么bufio 要比io 的讀寫更快速呢?根據(jù)網(wǎng)上的資料和閱讀源碼,以下來詳細(xì)解釋下bufio的高效如何實(shí)現(xiàn)的。

    bufio 包介紹

    bufio包實(shí)現(xiàn)了有緩沖的I/O。它包裝一個(gè)io.Reader或io.Writer接口對(duì)象,創(chuàng)建另一個(gè)也實(shí)現(xiàn)了該接口,且同時(shí)還提供了緩沖和一些文本I/O的幫助函數(shù)的對(duì)象。

    以上為官方包的介紹,在其中我們能了解到的信息如下:

    bufio 是通過緩沖來提高效率

    簡(jiǎn)單的說就是,把文件讀取進(jìn)緩沖(內(nèi)存)之后再讀取的時(shí)候就可以避免文件系統(tǒng)的io 從而提高速度。同理,在進(jìn)行寫操作時(shí),先把文件寫入緩沖(內(nèi)存),然后由緩沖寫入文件系統(tǒng)??赐暌陨辖忉層腥丝赡軙?huì)表示困惑了,直接把 內(nèi)容->文件 和 內(nèi)容->緩沖->文件相比, 緩沖區(qū)好像沒有起到作用嘛。其實(shí)緩沖區(qū)的設(shè)計(jì)是為了存儲(chǔ)多次的寫入,最后一口氣把緩沖區(qū)內(nèi)容寫入文件。下面會(huì)詳細(xì)解釋

    bufio 封裝了io.Reader或io.Writer接口對(duì)象,并創(chuàng)建另一個(gè)也實(shí)現(xiàn)了該接口的對(duì)象

    io.Reader或io.Writer 接口實(shí)現(xiàn)read() 和 write() 方法,對(duì)于實(shí)現(xiàn)這個(gè)接口的對(duì)象都是可以使用這兩個(gè)方法的

    注明:介紹內(nèi)容來自博主 LiangWenT

    ,原文鏈接: https://blog.csdn.net/LiangWenT/article/details/78995468 ,在查找資料時(shí),發(fā)現(xiàn)這篇博客的內(nèi)容很好理解

    bufio包實(shí)現(xiàn)了緩存IO。它包裝了io.Reader和io.Write對(duì)象,創(chuàng)建了另外的Reader和Writer對(duì)象,它們也實(shí)現(xiàn)了io.Reader和io.Write接口,具有緩存。注意:緩存是放在主存中,既然是保存在主存里,斷電會(huì)丟失數(shù)據(jù),那么要及時(shí)保存數(shù)據(jù)。

    二、常用內(nèi)容

    1、Reader類型

    NewReaderSize

    作用:NewReaderSize將rd封裝成一個(gè)帶緩存的bufio.Reader對(duì)象。緩存大小由size指定(如果小于16則會(huì)被設(shè)為16)。如果rd的基類型就是有足夠緩存的bufio.Reader類型,則直接將rd轉(zhuǎn)換為基類型返回。

    NewReader

    funcReader相當(dāng)于NewReaderSize(rd, 4096)

    Peek

    Peek返回緩存的一個(gè)切片,該切片引用緩存中前n個(gè)字節(jié)的數(shù)據(jù),該操作不會(huì)將數(shù)據(jù)讀出,只是引用,引用的數(shù)據(jù)在下一次讀取操作之前有效的。如果切片長(zhǎng)度小于n,則返回一個(gè)錯(cuò)誤信息說明原因。如果n大于緩存的總大小,則返回ErrBufferFull。

    Read

    Read從b中數(shù)據(jù)到p中,返回讀出的字節(jié)數(shù)和遇到的錯(cuò)誤。如果緩存不為空,則只能讀出緩沖中的數(shù)據(jù),不會(huì)從底層io.Reader中提取數(shù)據(jù),如果緩存為空,則:

    1、len(p) >= 緩存大小,則跳過緩存,直接從底層io.Reader中讀出到p中

    2、len(p)< 緩存大小,則先將數(shù)據(jù)從底層io.Reader中讀取到緩存中,再?gòu)木彺孀x取到p中。

    Buffered

    Buffered返回緩存中未讀取的數(shù)據(jù)的長(zhǎng)度。

    Discard

    Discard跳過后續(xù)的n個(gè)字節(jié)的數(shù)據(jù),返回跳過的字節(jié)數(shù)。

    Writer類型和方法

    write結(jié)構(gòu)

    NewWriteSize

    NewWriterSize將wr封裝成一個(gè)帶緩存的bufio.Writer對(duì)象,緩存大小由size指定(如果小于4096則會(huì)被設(shè)置未4096)。

    NewWrite

    NewWriter相等于NewWriterSize(wr, 4096)

    WriteString

    WriteString功能同Write,只不過寫入的是字符串

    WriteRune

    WriteRune向b寫入r的UTF-8編碼,返回r的編碼長(zhǎng)度。

    Flush

    Available

    Available 返回緩存中未使用的空間的長(zhǎng)度

    Buffered

    Buffered返回緩存中未提交的數(shù)據(jù)長(zhǎng)度

    Reset

    Reset將b的底層Write重新指定為w,同時(shí)丟棄緩存中的所有數(shù)據(jù),復(fù)位所有標(biāo)記和錯(cuò)誤信息。相當(dāng)于創(chuàng)建了一個(gè)新的bufio.Writer。

    GO中還提供了Scanner類型,處理一些比較簡(jiǎn)單的場(chǎng)景。如處理按行讀取輸入序列或空格分隔的詞等。

    內(nèi)容來自: 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命令行庫(kù)Cobra的使用

    寫了2次才寫完,內(nèi)容很長(zhǎng),翻譯了很久,內(nèi)容來源于Cobra github介紹。翻譯完也更全面的了解了Cobra,功能相當(dāng)強(qiáng)大完善,各種使用的場(chǎng)景都考慮到了。另外也擴(kuò)展了一些其它知識(shí),比如 命令行玩法 , Levenshtein distance 等等。以下是正文:

    Cobra提供簡(jiǎn)單的接口來創(chuàng)建強(qiáng)大的現(xiàn)代化CLI接口,比如git與go工具。Cobra同時(shí)也是一個(gè)程序, 用于創(chuàng)建CLI程序

    Cobra是建立在結(jié)構(gòu)的命令、參數(shù)和標(biāo)志之上。

    命令代表操作,參數(shù)和標(biāo)志是這些行動(dòng)的修飾符。

    最好的應(yīng)用程序就像讀取句子。用戶會(huì)知道如何使用本機(jī)應(yīng)用程序,因?yàn)樗麄儗⒗斫馊绾问褂盟?/p>

    比如下面的例子, server 是命令, port 是標(biāo)志:

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

    使用Cobra很簡(jiǎn)單。首先,使用 go get 安裝最新版本

    然后在你項(xiàng)目里引用Cobra

    通常基于Cobra的應(yīng)用程序?qū)⒆裱旅娴慕M織結(jié)構(gòu),當(dāng)然你也可以遵循自己的接口:

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

    Cobra提供自己的程序來創(chuàng)建你的程序并且添加你想要的命令。這是最簡(jiǎn)單的方式把Cobra添加到你的程序里。

    這里 你能找到相關(guān)信息

    使用Cobra,需要?jiǎng)?chuàng)建一個(gè)空的main.go文件和一個(gè)rootCmd文件。你可以選擇在合適的地方添加額外的命令。

    Cobra不需要特殊的構(gòu)造函數(shù)。簡(jiǎn)單的就可以創(chuàng)建你的命令。

    理想情況下你把這個(gè)放在在 app/cmd/root.go

    你會(huì)另外定義標(biāo)志和處理配置init()函數(shù)。

    比如 cmd/root.go

    你需要在main函數(shù)里執(zhí)行root命令。

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

    其它的命令通常定義在cmd/目錄下的自己文件內(nèi)

    如果你想創(chuàng)建一個(gè)version命令,你可以創(chuàng)建cmd/version.go文件,并在文件里這么寫:

    標(biāo)志提供修飾符控制動(dòng)作命令如何操作

    當(dāng)標(biāo)志定義好了,我們需要定義一個(gè)變量來關(guān)聯(lián)標(biāo)志

    '持久'表示每個(gè)在那個(gè)命令下的命令都將能分配到這個(gè)標(biāo)志。對(duì)于全局標(biāo)志,'持久'的標(biāo)志綁定在root上。

    Cobra默認(rèn)只在目標(biāo)命令上解析標(biāo)志,父命令忽略任何局部標(biāo)志。通過打開 Command.TraverseChildren Cobra將會(huì)在執(zhí)行任意目標(biāo)命令前解析標(biāo)志

    你同樣可以通過 viper 綁定標(biāo)志:

    在這個(gè)例子中,永久的標(biāo)記 author 被 viper 綁定, 注意 , 當(dāng)用戶沒有給 --author 提供值, author 不會(huì)被賦值。

    標(biāo)記默認(rèn)是可選的,如果你希望當(dāng)一個(gè)標(biāo)記沒有設(shè)置時(shí),命令行報(bào)錯(cuò),你可以標(biāo)記它為必須的

    驗(yàn)證位置參數(shù)可以通過 Command 的 Args 字段。

    內(nèi)置下列驗(yàn)證方法

    一個(gè)設(shè)置自定義驗(yàn)證的例子

    在下面的例子,我們定義了3個(gè)命令。2個(gè)在頂級(jí),一個(gè)(cmdTimes)是其中一個(gè)頂級(jí)命令的子命令。在這個(gè)例子里,由于沒有給 rootCmd 提供 Run ,單獨(dú)的root是不能運(yùn)行的,必須要有子命令。

    我們僅為一個(gè)命令定義了標(biāo)記。

    更多關(guān)于flags的文檔可以在 https://github.com/spf13/pflag 找到

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

    當(dāng)你的程序有子命令時(shí),Cobra 會(huì)自動(dòng)給你程序添加help命令。當(dāng)你運(yùn)行‘a(chǎn)pp help’,會(huì)調(diào)用help命令。另外,help同樣支持其它輸入命令。例如,你有一個(gè)沒有任何其它配置的命令叫‘create’,當(dāng)你調(diào)用‘a(chǎn)pp help create’ Corbra 將會(huì)起作用。

    下面的輸入是 Cobra 自動(dòng)生成的。除了命令和標(biāo)志的定義,其它不再需要。

    help 就跟其它命令一樣,并沒有特殊的邏輯或行為。事實(shí)上,你也可以提供你自己help如果你想的話。

    你能為默認(rèn)的命令,提供你自己的help命令或模板。使用下面的方法:

    后2個(gè)也將適用于任何子命令

    當(dāng)用戶提供無(wú)效的標(biāo)記或命令,Cobra 將會(huì)返回 用法 。

    你可能從上面的幫助意識(shí)到,默認(rèn)的幫助將被嵌入到用法里然后作為輸出。

    你能提供你自己的用法函數(shù)或模板給 Cobra 使用。

    比如幫助,方法和模板都可以重寫。

    如果Version字段設(shè)置到了根命令,Cobra 會(huì)提供了一個(gè)頂層 ‘--version’標(biāo)記。運(yùn)行帶上‘--version’標(biāo)記的程序,將會(huì)按照模板版本信息。模板可以通過 cmd.SetVersionTemplate(s string) 方法修改

    在命令運(yùn)行前或運(yùn)行后,再運(yùn)行方法非常容易。 PersistentPreRun 和 PreRun 方法將會(huì)在 Run 之前執(zhí)行。 PersistentPostRun 和 PostRun 方法將會(huì)在 Run 之后執(zhí)行。 Persistent*Run 方法會(huì)被子命令繼承,如果它們自己沒有定義的話。這些方法將按照下面的屬性執(zhí)行:

    下面的例子,2個(gè)命令都使用了上面的特性。當(dāng)子命令執(zhí)行的時(shí)候,它將執(zhí)行根命令的 PersistentPreRun ,但不會(huì)執(zhí)行根命令的 PersistentPostRun :

    輸出:

    Cobra 會(huì)自動(dòng)輸出建議,當(dāng)遇到“unknown command”錯(cuò)誤時(shí)。這使得當(dāng)輸入錯(cuò)誤時(shí), Cobra 的行為類似 git 命令。例如:

    建議會(huì)基于注冊(cè)的子命令自動(dòng)生成。使用了 Levenshtein distance 的實(shí)現(xiàn)。每一個(gè)注冊(cè)的命令會(huì)匹配2個(gè)距離(忽略大小寫)來提供建議。

    如果你希望在你的命令里,禁用建議或虛弱字符串的距離,使用:

    你可以通過 SuggestFor 來給命令提供明確的名詞建議。這個(gè)特性允許當(dāng)字符串不相近,但是意思與你的命令相近,別切你也不想給該命令設(shè)置別名。比如:

    Cobra 可以基于子命令,標(biāo)記,等生成文檔。以以下格式:

    Cobra 可以生成一個(gè)bash-completion文件。如果你給命令添加更多信息,這些completions可以非常強(qiáng)大和靈活。更多介紹在 Bash Completions 。

    三、golang【新人求助】關(guān)于菜鳥教程上 go build的問題

    ls是linux下列出文件和目錄的命令,在Windows下的對(duì)應(yīng)命令是dir。

    四、如何Golang開發(fā)Android應(yīng)用

    環(huán)境配置好復(fù)雜,我不得不嘮叨幾句。

    需要下載golang1.4rc版,下載ndk,然后編譯。 然后用go get 下載gobind這個(gè)工具, 然后,將寫好的代碼用gobind轉(zhuǎn)化下,然后使用特殊的編譯命令,將代碼編譯成.so文件,將生成的相關(guān)文件,放到android studio的項(xiàng)目中。然后java代碼中,利用jni調(diào)用引用的代碼。

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

    環(huán)境準(zhǔn)備

    一臺(tái)Linux 64的機(jī)器

    一個(gè)帶有AndroidStudioIDE的開發(fā)機(jī)器

    因?yàn)榄h(huán)境配置實(shí)在復(fù)雜,所以我們引入的docker。

    docker pull codeskyblue/docker-goandroid

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

    cd example; echo "view example projects

    docker起來之后,什么就都配置好了,NDK啦,java啦,GO的環(huán)境變量了,等等,并且還預(yù)裝了vim,gradle,tmux,git,syncthing,svn

    開始寫代碼

    寫代碼之前,先約定下目錄結(jié)構(gòu)

    go的代碼都放在src/golib下,編譯使用make.bash編譯腳本,看下這個(gè)文件樹

    .

    |-- app.iml

    |-- build.gradle

    |-- libs/armeabi-v7a # go編譯生成的so文件

    | `-- libgojni.so

    |-- main.go_tmpl # 一個(gè)模板文件,先不用管它

    |-- make.bash # 編譯腳本,用來生成.so和Java代碼

    `-- src

    |-- golib

    | |-- hi

    | | |-- go_hi�0�2�0�2�0�2 # 自動(dòng)生成的代碼

    | | | `-- go_hi.go

    | | `-- hi.go # 需要編寫的代碼

    | `-- main.go

    `-- main

    |-- AndroidManifest.xml

    |-- java

    | |-- go # 自動(dòng)生成的代碼

    | | |-- Go.java

    | | |-- Seq.java

    | | `-- hi

    | | `-- Hi.java

    | `-- me/shengxiang/gohello # 主要的邏輯代碼

    | `-- MainActivity.java

    `-- res

    我已經(jīng)寫了一個(gè)例子,先直接搞下來

    編譯下,試試行不行(就算不行問題應(yīng)該也不大,因?yàn)榇髥栴}都被我消滅了)

    cd GoHello/app

    ./make.bash

    ../gradlew build

    一切順利的話在build/outputs/apk下應(yīng)該可以看到app-debug.apk這個(gè)文件。(劇透下,這個(gè)文件只有800多K)

    編譯好的我放到qiniu上了,可以點(diǎn)擊下載看看

    下面可以嘗試改改,我拋磚引玉說下

    打開hi.go這個(gè)文件

    hi.go的內(nèi)容,比較簡(jiǎn)單,我們寫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();

    }

    });

    編譯運(yùn)行下,把生成的apk安裝到手機(jī)上試試。

    原理解讀(有興趣的接著看)

    首先說下gobind這個(gè)工具。

    go_hi/go_hi.go這個(gè)文件時(shí)通過gobind這個(gè)工具生成的,用來配合一個(gè)簡(jiǎn)單的程序,生成.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)

    }

    這個(gè)簡(jiǎn)單的程序內(nèi)容是這樣的

    // 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文件內(nèi)容是這樣的

    import ...

    import go.Go; // 引入Go這個(gè)包

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

    public class MainActivity extends Activity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    Go.init(getApplicationContext()); // 初始化兩個(gè)線程

    Hi.Hello("world");

    }

    }

    其中有一句Go.init(...)這里再看go.Go這個(gè)包是什么樣子的

    public final class Go {

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

    public static void init(Context context) {

    ... 判斷該函數(shù)是否該執(zhí)行的代碼 -- 省略 --

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

    new Thread("GoMain") {

    public void run() {

    Go.run(); // run()是一個(gè)native方法

    }

    }.start();

    Go.waitForRun(); // 這個(gè)也是一個(gè)native方法

    // 這部分可以理解為,啟動(dòng)了一個(gè)后臺(tái)線程不斷的接收結(jié)果到緩存中。

    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,這個(gè)文件也是gobind生成的,是用來給java方便的調(diào)用.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這部分實(shí)際上最終調(diào)用的是一段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)

    }

    轉(zhuǎn)載僅供參考,版權(quán)屬于原作者。祝你愉快,滿意請(qǐng)采納哦

    以上就是關(guān)于golang生成文件快照相關(guān)問題的回答。希望能幫到你,如有更多相關(guān)問題,您也可以聯(lián)系我們的客服進(jìn)行咨詢,客服也會(huì)為您講解更多精彩的知識(shí)和內(nèi)容。


    推薦閱讀:

    小智logo在線制作神器

    電視臺(tái)logo設(shè)計(jì)(電視臺(tái)logo設(shè)計(jì)說明)

    good趣味記憶法(grape趣味記憶法)

    騰訊游戲內(nèi)測(cè)資格怎么獲得(騰訊游戲的內(nèi)測(cè)資格怎么獲?。?/a>

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