GoLang-データストレージ(上)

25850 ワード

データストレージは、ファイルストレージ、リレーショナル・データベース(SQL)、非リレーショナル・データベース(NoSQL)の3つに分類されます.本稿では、主にファイルストレージの実現方法について説明します.
ファイルストレージは、txt読み書きなどの一般ファイル、CSVファイル、データのシーケンス化、永続化など、異なるファイルに基づいて異なるストレージ方式を実現します.
通常ファイル(txt読み書きなど)
一般ファイルの読み書きはosまたはio/ioutilパッケージを用いて実現でき、両者の実現方式は以下の通りである.
package main

import (
	"fmt"
	"io/ioutil"
	"os"
)

func main() {
	//   ioutil WriteFile         
	data := []byte("Hello World!
"
) err := ioutil.WriteFile("data1.txt", data, 0644) if err != nil { panic(err) } // ioutil ReadFile read1, _ := ioutil.ReadFile("data1.txt") fmt.Print(string(read1)) // os Create file1, _ := os.Create("data2.txt") // defer, file1 defer file1.Close() // file1 bytes, _ := file1.Write(data) fmt.Printf("Wrote %d bytes to file
"
, bytes) // os Open data2.txt, file2 file2, _ := os.Open("data2.txt") defer file2.Close() // data read2 := make([]byte, len(data)) // file2 Read , read2 bytes, _ = file2.Read(read2) fmt.Printf("Read %d bytes from file
"
, bytes) fmt.Println(string(read2)) }

CSVファイル
CSV形式は、テキストエディタがテキストと数値からなる表データを読み書きやすくするファイル形式です.CSVの応用は非常に広く、マイクロソフトのExcelやアップルのNumbersを含むほとんどのスプレッドシートプログラムはCSVフォーマットをサポートしているため、Goを含む多くのプログラミング言語はCSVファイルデータの生成と処理が可能な関数ライブラリを提供している.Go言語では、CSVファイルはencoding/csvパッケージで操作でき、実装コードは以下の通りです.
package main

import (
	"encoding/csv"
	"fmt"
	"os"
	"strconv"
)

type Post struct {
	Id int
	Content string
	Author string
}
func main() {
	//     posts.csv
	csvFile, err := os.Create("posts.csv")
	if err != nil {
		panic(err)
		}
	defer csvFile.Close()
	//     
	allPosts := []Post{
				Post{Id: 1, Content: "Hello World!", Author: "Sau Sheong"},
				Post{Id: 2, Content: "Bonjour Monde!", Author: "Pierre"},
				Post{Id: 3, Content: "Hola Mundo!", Author: "Pedro"},
				Post{Id: 4, Content: "Greetings Earthlings!", Author: "Sau Sheong"},}
	//   csv NewWriter     csvFile      
	writer := csv.NewWriter(csvFile)
	//   allPosts     ,         CSV  
	for _, post := range allPosts {
		//  strconv.Itoa(post.Id)        
		//   line        
		line := []string{strconv.Itoa(post.Id), post.Content, post.Author}
		//    line  CSV  
		err := writer.Write(line)
		if err != nil {
			panic(err)
			}
		}
	//   Flush                           
	writer.Flush()

	// ………………………………………………………………………………………   ………………………………………………………………………………………
	
	//   CSV  
	file, err := os.Open("posts.csv")
	if err != nil {
		panic(err)
		}
	defer file.Close()
	//   csv NewWriter     csvFile      
	reader := csv.NewReader(file)
	//              
	//   FieldsPerRecord     ,  CSV                  ,Go        。
	//   FieldsPerRecord   0,                        FieldsPerRecord  。
	//   FieldsPerRecord     ,                     ,          。
	reader.FieldsPerRecord = -1
	//         
	//        Read()
	record, err := reader.ReadAll()
	if err != nil {
		panic(err)
		}
	//            
	var posts []Post
	for _, item := range record {
		//    Id     
		id, _ := strconv.ParseInt(item[0], 0, 0)
		post := Post{Id: int(id), Content: item[1], Author: item[2]}
		posts = append(posts, post)
		}
	fmt.Println(posts[0].Id)
	fmt.Println(posts[0].Content)
	fmt.Println(posts[0].Author)
}

データのシーケンス化と永続化
goのencoding/gobパケットはgobからなるストリーム(stream)を管理するために用いられ、エンコーダとデコーダとの間で交換されるバイナリデータであり、このデータはもともとシーケンス化およびデータ伝送のために設計されていたが、データの永続化に用いられ、ユーザが容易にファイルを読み書きできるようにするために、エンコーダとデコーダは一般的にプログラムのライタとリーダをそれぞれ包む.簡単に言えば、goのencoding/gobパッケージはpythonのpickleモジュールに似ており、両者が実現する機能は同じである.しかし、両者を比較すると、encoding/gobパッケージの使用方法はpythonの便利さがなく、具体的な使用過程は以下の通りであることが分かった.
package main

import (
	"bytes"
	"encoding/gob"
	"fmt"
	"io/ioutil"
)

type Post struct {
	Id int
	Content string
	Author string
}

func store(data interface{}, filename string) {
	//          buffer
	//     Read   Write       (variable-sized)     
	//     ,bytes.Buffer          。
	buffer := new(bytes.Buffer)
	//       buffer    ,     encoder
	encoder := gob.NewEncoder(buffer)
	//    data     encoder(       buffer)
	err := encoder.Encode(data)
	if err != nil {
		panic(err)
	}
	//       buffer               ,         
	err = ioutil.WriteFile(filename, buffer.Bytes(), 0600)
	if err != nil {
		panic(err)
	}
}

func load(data interface{}, filename string) {
	//     filename     
	raw, err := ioutil.ReadFile(filename)
	if err != nil {
		panic(err)
	}
	//          buffer,      raw          buffer
	buffer := bytes.NewBuffer(raw)
	//         buffer     dec
	dec := gob.NewDecoder(buffer)
	//            data
	err = dec.Decode(data)
	if err != nil {
		panic(err)
	}
}

func main() {
	post := Post{Id: 1, Content: "Hello World!", Author: "Sau Sheong"}
	store(post, "post1")
	var postRead Post
	load(&postRead, "post1")
	fmt.Println(postRead.Id)
}