浅谈GoLang几种读文件方式的比较

GoLang提供了很多读文件的方式,一般来说常用的有三种。使用Read加上buffer,使用bufio库和ioutil 库。

那他们的效率如何呢?用一个简单的程序来评测一下:

package main 

import(
  "fmt"
  "os"
  "flag"
  "io"
  "io/ioutil"
  "bufio"
  "time"
) 

func read1(path string)string{
  fi,err := os.Open(path)
  if err != nil{
    panic(err)
  }
  defer fi.Close() 

  chunks := make([]byte,1024,1024)
  buf := make([]byte,1024)
  for{
    n,err := fi.Read(buf)
    if err != nil && err != io.EOF{panic(err)}
    if 0 ==n {break}
    chunks=append(chunks,buf[:n]...)
    // fmt.Println(string(buf[:n]))
  }
  return string(chunks)
} 

func read2(path string)string{
  fi,err := os.Open(path)
  if err != nil{panic(err)}
  defer fi.Close()
  r := bufio.NewReader(fi) 

  chunks := make([]byte,1024,1024) 

  buf := make([]byte,1024)
  for{
    n,err := r.Read(buf)
    if err != nil && err != io.EOF{panic(err)}
    if 0 ==n {break}
    chunks=append(chunks,buf[:n]...)
    // fmt.Println(string(buf[:n]))
  }
  return string(chunks)
} 

func read3(path string)string{
  fi,err := os.Open(path)
  if err != nil{panic(err)}
  defer fi.Close()
  fd,err := ioutil.ReadAll(fi)
  // fmt.Println(string(fd))
  return string(fd)
} 

func main(){ 

  flag.Parse()
  file := flag.Arg(0)
  f,err := ioutil.ReadFile(file)
  if err != nil{
    fmt.Printf("%s\n",err)
    panic(err)
  }
  fmt.Println(string(f))
  start := time.Now()
  read1(file)
  t1 := time.Now()
  fmt.Printf("Cost time %v\n",t1.Sub(start))
  read2(file)
  t2 := time.Now()
  fmt.Printf("Cost time %v\n",t2.Sub(t1))
  read3(file)
  t3 := time.Now()
  fmt.Printf("Cost time %v\n",t3.Sub(t2)) 

} 

运行命令go run read.go filename, 制定需要读取的文件就可以了。这里我比较了读取13.7MB的日志文件,三种方式分别消耗的时间是:

Cost time 105.006ms
Cost time 68.0039ms
Cost time 31.0018ms 

读取29.3MB的媒体文件:

Cost time 390.0223ms
Cost time 194.0111ms
Cost time 83.0048ms 

读取302MB的媒体文件

Cost time 40.8043338s
Cost time 1m5.0407201s
Cost time 8.8155043s 

这个差距就很明显了,ioutil提供的方法效率就是高。有空可以再从代码层面再去分析一下。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Golang常量iota的使用实例

    Codes package main import "fmt" type color byte const ( black color = iota red blue ) func test(c color) { fmt.Println(c) } func main() { const ( x = iota // 0 y // 1 z // 2 ) fmt.Printf("x=%v, y=%v, z=%v\n", x, y, z) const ( _ = iota

  • Go系列教程之反射的用法

    反射是 Go 语言的高级主题之一.我会尽可能让它变得简单易懂. 本教程分为如下小节. 什么是反射? 为何需要检查变量,确定变量的类型? reflect 包 reflect.Type 和 reflect.Value reflect.Kind NumField() 和 Field() 方法 Int() 和 String() 方法 完整的程序 我们应该使用反射吗? 让我们来逐个讨论这些章节. 什么是反射? 反射就是程序能够在运行时检查变量和值,求出它们的类型.你可能还不太懂,这没关系.在本教程结束后,

  • Go语言中常量定义方法实例分析

    本文实例讲述了Go语言中常量定义方法.分享给大家供大家参考.具体分析如下: 常量的定义与变量类似,只不过使用 const 关键字. 常量可以是字符.字符串.布尔或数字类型的值. 复制代码 代码如下: package main import "fmt" const Pi = 3.14 func main() {     const World = "世界"     fmt.Println("Hello", World)     fmt.Printl

  • GO语言中的常量

    常量是程序中最基础的元素,在定义之后就不能再重新赋值了.Go语言中的常量类型有布尔常量.整数常量.浮点数常量. 字符常量.字符串常量和复数常量 . 布尔常量 复制代码 代码如下: const x = true fmt.Print(x) //输出true 整数常量 复制代码 代码如下: const x = 20 fmt.Print(x) //输出20 浮点数常量 复制代码 代码如下: constx = 0.618 fmt.Print(x) //输出%f0.618 字符常量 复制代码 代码如下: c

  • 详解Golang编程中的常量与变量

    Go语言常量 常量是指该程序可能无法在其执行期间改变的固定值.这些固定值也被称为文字. 常量可以是任何像一个整型常量,一个浮点常量,字符常量或字符串文字的基本数据类型.还有枚举常量. 常量是一样,只是它们的值不能自己定义后进行修改常规变量处理. 整型常量 一个整数文字可以是十进制,八进制,或十六进制常数.前缀指定基或基数:0x或0X的十六进制,0表示八进制,并没有为十进制. 一个整数文字也可以有一个后缀为U和L的组合,分别为无符号和长整型.后缀可以是大写或小写,并且可以以任意顺序. 这里是整数常

  • Go并发调用的超时处理的方法

    之前有聊过 golang 的协程,我发觉似乎还很理论,特别是在并发安全上,所以特结合网上的一些例子,来试验下go routine中 的 channel, select, context 的妙用. 场景-微服务调用 我们用 gin(一个web框架) 作为处理请求的工具,需求是这样的: 一个请求 X 会去并行调用 A, B, C 三个方法,并把三个方法返回的结果加起来作为 X 请求的 Response. 但是我们这个 Response 是有时间要求的(不能超过3秒的响应时间),可能 A, B, C

  • Golang学习笔记(二):类型、变量、常量

    基本类型 1.基本类型列表 复制代码 代码如下: 类型        长度     说明 bool         1      true/false,默认false, 不能把非0值当做true(不用数字代表true/false) byte         1      uint8 别名 rune         4      int32别名. 代表一个unicode code point int/unit            一来所运行的平台,32bit/64bit int8/uint8  

  • GOLANG使用Context管理关联goroutine的方法

    一般一个业务很少不用到goroutine的,因为很多方法是需要等待的,例如http.Server.ListenAndServe这个就是等待的,除非关闭了Server或Listener,否则是不会返回的.除非是一个API服务器,否则肯定需要另外起goroutine发起其他的服务,而且对于API服务器来说,在http.Handler的处理函数中一般也需要起goroutine,如何管理这些goroutine,在GOLANG1.7提供context.Context. 先看一个简单的,如果启动两个goro

  • Go routine调度详解

    goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字即可启动一个协程,并且它是处于异步方式运行,你不需要等它运行完成以后在执行以后的代码. go func()//通过go关键字启动一个协程来运行函数 go routine的调度原理和操作系统的线层调度是比较相似的.这里我们将介绍go routine的相关知识. goroutine(有人也称之为协程)本质上

  • GOLANG使用Context实现传值、超时和取消的方法

    GO1.7之后,新增了context.Context这个package,实现goroutine的管理. Context基本的用法参考GOLANG使用Context管理关联goroutine. 实际上,Context还有个非常重要的作用,就是设置超时.比如,如果我们有个API是这样设计的: type Packet interface { encoding.BinaryMarshaler encoding.BinaryUnmarshaler } type Stack struct { } func

随机推荐