首页 > 编程语言 >Go源码阅读——github.com/medcl/esm —— file.go

Go源码阅读——github.com/medcl/esm —— file.go

时间:2023-05-09 11:24:40浏览次数:41  
标签:github err License 源码 file go os

esm(An Elasticsearch Migration Tool)—— file.go

https://github.com/medcl/esm release: 8.7.1

通过阅读好的源代码,细致思考,理性分析并借鉴优秀实践经验,提高 zuoyang 的编程水平,所谓 "他山之石,可以攻玉"  该是如此吧。 

 

/*
Copyright 2016 Medcl (m AT medcl.net)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
	"bufio"
	"encoding/json"
	"io"
	"os"
	"sync"

	"github.com/cheggaaa/pb"
	log "github.com/cihub/seelog"
)

/*检查文件是否存在。*/
func checkFileIsExist(filename string) bool {
	var exist = true
	/*
		os.Stat() 是 go 的一个函数,用于获取文件或目录的基本信息,如文件大小,修改时间,文件权限等。
		os.IsNotExist() 是 go 中的一个函数,用于检查指定的错误是否表示文件或目录不存在的情况。os.IsNotExist(err error) bool 接受一个 error 类型的参数,然后返回一个布尔值。
		当参数 err 表示一个文件或目录不存在的错误时,返回 true,否则返回 false。
	*/
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		exist = false
	}
	return exist
}

/*读取文件并将其解析为 JSON 的函数*/
func (m *Migrator) NewFileReadWorker(pb *pb.ProgressBar, wg *sync.WaitGroup) {
	log.Debug("start reading file")
	f, err := os.Open(m.Config.DumpInputFile)
	if err != nil {
		log.Error(err)
		return
	}

	defer f.Close()
	r := bufio.NewReader(f)
	lineCount := 0
	for {
		/*按行读取一个文件中的数据*/
		line, err := r.ReadString('\n')
		if io.EOF == err || nil != err {
			break
		}
		/*使用计数器变量(lineCount)来记录文件中的行数*/
		lineCount += 1
		js := map[string]interface{}{}

		/*将读取的行数据解析成json数据*/
		err = DecodeJson(line, &js)
		if err != nil {
			log.Error(err)
			continue
		}
		/*发送到通道 m.DocChan*/
		m.DocChan <- js
		/*每读取一行就让进度条(pb)加1*/
		pb.Increment()
	}

	defer f.Close()
	log.Debug("end reading file")
	close(m.DocChan)
	wg.Done()
}

/*用于将 Elasticsearch 中的数据写入到一个文件中*/
func (c *Migrator) NewFileDumpWorker(pb *pb.ProgressBar, wg *sync.WaitGroup) {
	var f *os.File
	var err1 error

	/*判断文件是否存在,如果存在,*/
	if checkFileIsExist(c.Config.DumpOutFile) {
		/*
			os.OpenFile()函数会打开指定路径的 c.Config.DumpOutFile 文件,并返回一个额 *os.File 类型的文件。
			os.O_APPEND:表示在已有的文件内容的后面追加新的内容。
			os.O_WRONLY:表示只写模式打开文件。
			os.ModeAppend:是一个文件的模式,它表示如果文件存在,则在文件末尾追加写操作的数据。
			还有其他的,类似:
				os.O_RDONLY: 表示只读模式打开文件。
				os.O_WRONLY: 表示只写模式打开文件。
				os.O_RDWR:   表示读写模式打开文件。
				os.O_APPEND: 表示在文件末尾添加数据而不是覆盖原有内容。
				os.O_CREATE: 表示如果文件不存在,就创建该文件。
				os.O_TRUNC:  表示打开文件时清空文件内容。
				os.O_EXCL: 与os.O_CREATE同时使用,表示如果文件已经存在,则不进行创建,返回一个错误。
				os.O_SYNC: 打开文件时,每次写入都会被同步到硬盘上,类似于fsync()函数。
				os.O_NONBLOCK: 如果文件无法立即打开,不会等待,而是立即返回一个错误。
			os.ModeAppend 和 os.O_APPEND 区别:
				os.ModeAppend 是文件的模式,指定该模式后程序可以向文件中追加内容,不会清空文件。如果该文件不存在,会创建一个新的文件并拥有该模式。
				os.O_APPEND 则是文件打开的选项,指定该选项后程序可以在文件末尾追加内容,而不是覆盖之前的内容。如果该文件不存在,会返回一个错误。
		*/
		f, err1 = os.OpenFile(c.Config.DumpOutFile, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
		if err1 != nil {
			log.Error(err1)
			return
		}

	} else {
		f, err1 = os.Create(c.Config.DumpOutFile)
		if err1 != nil {
			log.Error(err1)
			return
		}
	}
	/*
	   这段代码是使用 go 语言标准库中的 bufio 包中的 NewWriter 方法创建一个将数据写入文件 f 中的缓存 Writer 对象 w。
	   通过使用缓存来写入数据可以提高程序写入文件的效率,因为它避免了对文件的多次访问和IO操作次数的减少。 在之后的操作中,使用 w.Write 方法将数据写入缓存中。
	   当缓存满时,它将自动将缓存中的数据刷新到物理磁盘上的文件中。如果想确认数据已经被写入磁盘,可以调用 w.Flush() 方法来刷新缓存并将所有数据写入文件中。
	*/
	w := bufio.NewWriter(f)

READ_DOCS:
	for {

		/*
			从 channel c.DocChan 中读取一个文档并将其赋值给变量 docI;
			变量 open 会返回一个布尔值,用于指示通道是否已经被关闭。
			这样可以避免在通道关闭前读取到空值。如果没有文档可读取或者通道已经关闭,那么程序将结束循环并退出。
		*/
		docI, open := <-c.DocChan
		/*
			程序将检查文档 docI 中是否包含一个名为 status 的键。如果包含,那么将检查 status 的值是否为 404。
			这个检查主要是用来处理 Elasticsearch 查询时出现的错误,避免这些错误对程序的正常运行造成影响。
		*/
		if status, ok := docI["status"]; ok {
			/*如果是,那么表明在查询 Elasticsearch 索引时出现了错误。*/
			if status.(int) == 404 {
				/*程序将打印一条错误日志,并执行 continue 语句,继续循环读取下一个文档。*/
				log.Error("error: ", docI["response"])
				continue
			}
		}

		/*
			对读取到的文档数据进行完整性检查,确保其中包含了 Elasticsearch 数据库中所必需的字段,以便程序可以正确地处理数据。
			代码通过遍历一个包含字段名的字符串数组 {"_index", "_type", "_source", "_id"} ,逐一检查文档 docI 是否包含了这些字段。
		*/
		for _, key := range []string{"_index", "_type", "_source", "_id"} {
			/*
				如果文档中缺少了任何一个必需的字段,那么 ok 变量将返回 false,并通过 break 语句中断循环以继续读取下一个文档。
				这样的检查可以确保程序不会处理缺少必要字段的文档,从而避免出现错误。例如,如果文档中缺少 _id 字段,那么程序在处理文档时可能会引发异常。
				因此,通过进行必要的完整性检查,可以保证程序在处理数据时能够正确地读取和使用必要的字段。
			*/
			if _, ok := docI[key]; !ok {
				break READ_DOCS
			}
		}

		/*将 docI 这个数据结构编码为 JSON 格式的字节数组,其中 jsr 表示 JSON 序列化之后的字节数组,err 则是 json.Marshal 调用过程中可能出现的错误。*/
		jsr, err := json.Marshal(docI)
		/*
			将 JSON 序列化之后的字节数组转换成字符串形式,并打印出来。
			log.Trace 是 log 包中提供的一个日志级别,用于记录比 Debug 更详细的日志信息。
			log 包提供了六个不同级别的日志记录方法,分别是:Trace、Debug、Info、Warn、Error 和 Fatal。
		*/
		log.Trace(string(jsr))
		if err != nil {
			log.Error(err)
		}
		/*
			将 jsr 的内容以字符串的形式写入到 n 中。
			w 表示一个实现了 io.Writer 接口的对象,通过 WriteString 方法将 jsr 内容转换为字符串并写入 w 中。最终函数返回写入的字节数和可能出现的错误信息。
		*/
		n, err := w.WriteString(string(jsr))
		if err != nil {
			log.Error(n, err)
		}
		w.WriteString("\n")
		pb.Increment()

		// if channel is closed flush and gtfo
		if !open {
			goto WORKER_DONE
		}
	}

WORKER_DONE:
	w.Flush()
	f.Close()

	wg.Done()
	log.Debug("file dump finished")
}

标签:github,err,License,源码,file,go,os
From: https://www.cnblogs.com/zuoyang/p/17384328.html

相关文章

  • Windows下cygwin编译redis源码
    准备环境安装cygwin64下载地址:https://www.cygwin.com/运行安装程序,一直下一步选择阿里镜像,目前试过163,会比阿里慢需要选择的包有make、pkg-config、pythongcc相关是否需要还不确定安装重新可重复执行,缺少的包下次可以补上点击下一步等待安装完成即可下载redis源码https://......
  • Go源码阅读——github.com/medcl/esm —— esapi.go
    esm(AnElasticsearchMigrationTool)—— esapi.go https://github.com/medcl/esmrelease:8.7.1通过阅读好的源代码,细致思考,理性分析并借鉴优秀实践经验,提高zuoyang的编程水平,所谓"他山之石,可以攻玉" 该是如此吧。 /*Copyright2016Medcl(mATmedcl.net)Licen......
  • 咚咚咚,你的王国之泪已上线「GitHub 热点速览」
    本周最大的热点,莫过于Mojo语言了,几大媒体均有报道这门兼顾Python优点和性能的新语言。当然还有凭借Switch游戏《塞尔达传说·王国之泪》登上热榜,获得3,500+star的Switch模拟器Ryujinx。当然,还有一些日常工作可能用到的测试工具gitleaks、网页加速qwik,处理数据的c......
  • 台式机装Ubuntu 遇到“no root file system is defined”、安装类型上没有“删除直接
    今日,给清华要的两台电脑终于拿到手了(下午拿到的,具体坎坷经历见日报)。开始配环境,主要是三个步骤:1、装Linux2、装网卡和网卡驱动3、装GNU_radio一系列环境(见我上个月虚拟机的操作方案)今天完成了1和2.最恶心的是1.首先报的错误是,norootfilesystemisdefined,确实,但是为什么......
  • java基于ssm的求职招聘管理系统、校园求职招聘管理系统,附源码+数据库,适合毕业设计、课
    1、项目介绍​该求职招聘网站基于B/S架构,采用SSM框架,运用JSP网页开发技术,并结合MySQL数据库,为招聘者和求职者搭建了一个高效、便捷的网络招聘平台。系统总共有三个角色:求职者、招聘者、管理员​本系统分别为前台求职招聘和后台系统管理,功能如下:​1.前台求职招聘​前台首......
  • makefile autotools
    autotools使用步骤(用autotools制作makefile)(betheme.net)  makefile详解-一叶飘落尽知秋-博客园(cnblogs.com)   直接make文件名就自动帮你编译了运行vimmakefile创建一个 控制台make就生成了   windwos中引入库不需要其他什么,linux就需要了 ......
  • Go源码阅读——github.com/medcl/esm —— bulk.go
    esm(AnElasticsearchMigrationTool)—— bulk.gohttps://github.com/medcl/esmrelease:8.7.1通过阅读好的源代码,细致思考,理性分析并借鉴优秀实践经验,提高zuoyang的编程水平,所谓"他山之石,可以攻玉" 该是如此吧。 /*Copyright2016Medcl(mATmedcl.net)Licensed......
  • 解决git错误: error: The following untracked working tree files would be overwrit
    在我本地上进行gitpull的时候,出现这个错误:error:Thefollowinguntrackedworkingtreefileswouldbeoverwrittenbymerge:config/config.php 这是因为,本地上有一个文件,没有被git管理,但是git上有了同名的文件。怎么解决呢? 1。如果不需要本地的文件了,那么直接......
  • GitHub搭建个人博客2023
    1.登录github2.上传一个index.html的文件3.点击settings-->然后点击pages3.选择分支->点击save ......
  • Dockerfile、常用和不常用命令、dockerfile构建一个djagno项目、docker私有仓库、镜像
    目录1Dockerfile1.1常用和不常用命令1.2dockerfile构建一个djagno项目2docker私有仓库2.1镜像传到官方仓库2.2镜像分层2.3私有仓库搭建3dockercompose介绍4dockercompose部署flask+redis项目4.1新建flask项目app.py4.2编写Dockerfile--》用于构建flask项目的镜像4.3......