-
當前位置:首頁 > 創(chuàng)意學院 > 技術 > 專題列表 > 正文
golang生成文件快照(golang上傳文件)
大家好!今天讓創(chuàng)意嶺的小編來大家介紹下關于golang生成文件快照的問題,以下是小編對此問題的歸納整理,讓我們一起來看看吧。
開始之前先推薦一個非常厲害的Ai人工智能工具,一鍵生成原創(chuàng)文章、方案、文案、工作計劃、工作報告、論文、代碼、作文、做題和對話答疑等等
只需要輸入關鍵詞,就能返回你想要的內容,越精準,寫出的就越詳細,有微信小程序端、在線網頁版、PC客戶端
創(chuàng)意嶺作為行業(yè)內優(yōu)秀的企業(yè),服務客戶遍布全球各地,如需了解SEO相關業(yè)務請撥打電話175-8598-2043,或添加微信:1454722008
本文目錄:
一、golang中bufio包
一、介紹go標準庫中的bufio
最近用golang寫了一個處理文件的腳本,由于其中涉及到了文件讀寫,開始使用golang中的 io 包,后來發(fā)現golang 中提供了一個bufio的包,使用這個包可以大幅提高文件讀寫的效率,于是在網上搜索同樣的文件讀寫為什么bufio 要比io 的讀寫更快速呢?根據網上的資料和閱讀源碼,以下來詳細解釋下bufio的高效如何實現的。
bufio 包介紹
bufio包實現了有緩沖的I/O。它包裝一個io.Reader或io.Writer接口對象,創(chuàng)建另一個也實現了該接口,且同時還提供了緩沖和一些文本I/O的幫助函數的對象。
以上為官方包的介紹,在其中我們能了解到的信息如下:
bufio 是通過緩沖來提高效率
簡單的說就是,把文件讀取進緩沖(內存)之后再讀取的時候就可以避免文件系統(tǒng)的io 從而提高速度。同理,在進行寫操作時,先把文件寫入緩沖(內存),然后由緩沖寫入文件系統(tǒng)??赐暌陨辖忉層腥丝赡軙硎纠Щ罅?,直接把 內容->文件 和 內容->緩沖->文件相比, 緩沖區(qū)好像沒有起到作用嘛。其實緩沖區(qū)的設計是為了存儲多次的寫入,最后一口氣把緩沖區(qū)內容寫入文件。下面會詳細解釋
bufio 封裝了io.Reader或io.Writer接口對象,并創(chuàng)建另一個也實現了該接口的對象
io.Reader或io.Writer 接口實現read() 和 write() 方法,對于實現這個接口的對象都是可以使用這兩個方法的
注明:介紹內容來自博主 LiangWenT
,原文鏈接: https://blog.csdn.net/LiangWenT/article/details/78995468 ,在查找資料時,發(fā)現這篇博客的內容很好理解
bufio包實現了緩存IO。它包裝了io.Reader和io.Write對象,創(chuàng)建了另外的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個字節(jié)的數據,該操作不會將數據讀出,只是引用,引用的數據在下一次讀取操作之前有效的。如果切片長度小于n,則返回一個錯誤信息說明原因。如果n大于緩存的總大小,則返回ErrBufferFull。
Read
Read從b中數據到p中,返回讀出的字節(jié)數和遇到的錯誤。如果緩存不為空,則只能讀出緩沖中的數據,不會從底層io.Reader中提取數據,如果緩存為空,則:
1、len(p) >= 緩存大小,則跳過緩存,直接從底層io.Reader中讀出到p中
2、len(p)< 緩存大小,則先將數據從底層io.Reader中讀取到緩存中,再從緩存讀取到p中。
Buffered
Buffered返回緩存中未讀取的數據的長度。
Discard
Discard跳過后續(xù)的n個字節(jié)的數據,返回跳過的字節(jié)數。
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,同時丟棄緩存中的所有數據,復位所有標記和錯誤信息。相當于創(chuàng)建了一個新的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提供簡單的接口來創(chuàng)建強大的現代化CLI接口,比如git與go工具。Cobra同時也是一個程序, 用于創(chuàng)建CLI程序
Cobra是建立在結構的命令、參數和標志之上。
命令代表操作,參數和標志是這些行動的修飾符。
最好的應用程序就像讀取句子。用戶會知道如何使用本機應用程序,因為他們將理解如何使用它。
比如下面的例子, server 是命令, port 是標志:
在下面的命令,我們告訴Git克隆url地址bare
使用Cobra很簡單。首先,使用 go get 安裝最新版本
然后在你項目里引用Cobra
通?;贑obra的應用程序將遵循下面的組織結構,當然你也可以遵循自己的接口:
在Cobra應用程序中,通常main.go文件非??斩础K饕桓梢患拢撼跏蓟疌obra。
Cobra提供自己的程序來創(chuàng)建你的程序并且添加你想要的命令。這是最簡單的方式把Cobra添加到你的程序里。
這里 你能找到相關信息
使用Cobra,需要創(chuàng)建一個空的main.go文件和一個rootCmd文件。你可以選擇在合適的地方添加額外的命令。
Cobra不需要特殊的構造函數。簡單的就可以創(chuàng)建你的命令。
理想情況下你把這個放在在 app/cmd/root.go
你會另外定義標志和處理配置init()函數。
比如 cmd/root.go
你需要在main函數里執(zhí)行root命令。
通常main.go文件非??斩?。它主要只干一件事:初始化Cobra。
其它的命令通常定義在cmd/目錄下的自己文件內
如果你想創(chuàng)建一個version命令,你可以創(chuàng)建cmd/version.go文件,并在文件里這么寫:
標志提供修飾符控制動作命令如何操作
當標志定義好了,我們需要定義一個變量來關聯(lián)標志
'持久'表示每個在那個命令下的命令都將能分配到這個標志。對于全局標志,'持久'的標志綁定在root上。
Cobra默認只在目標命令上解析標志,父命令忽略任何局部標志。通過打開 Command.TraverseChildren Cobra將會在執(zhí)行任意目標命令前解析標志
你同樣可以通過 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 之前執(zhí)行。 PersistentPostRun 和 PostRun 方法將會在 Run 之后執(zhí)行。 Persistent*Run 方法會被子命令繼承,如果它們自己沒有定義的話。這些方法將按照下面的屬性執(zhí)行:
下面的例子,2個命令都使用了上面的特性。當子命令執(zhí)行的時候,它將執(zhí)行根命令的 PersistentPreRun ,但不會執(zhí)行根命令的 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開發(fā)Android應用
環(huán)境配置好復雜,我不得不嘮叨幾句。
需要下載golang1.4rc版,下載ndk,然后編譯。 然后用go get 下載gobind這個工具, 然后,將寫好的代碼用gobind轉化下,然后使用特殊的編譯命令,將代碼編譯成.so文件,將生成的相關文件,放到android studio的項目中。然后java代碼中,利用jni調用引用的代碼。
... 好,接著往下看吧。
環(huán)境準備
一臺Linux 64的機器
一個帶有AndroidStudioIDE的開發(fā)機器
因為環(huán)境配置實在復雜,所以我們引入的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)境變量了,等等,并且還預裝了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) {
... 判斷該函數是否該執(zhí)行的代碼 -- 省略 --
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生成文件快照相關問題的回答。希望能幫到你,如有更多相關問題,您也可以聯(lián)系我們的客服進行咨詢,客服也會為您講解更多精彩的知識和內容。
推薦閱讀:
騰訊游戲內測資格怎么獲得(騰訊游戲的內測資格怎么獲?。?/a>