您的位置:

关于golangwrite的信息

本文目录一览:

golang ioutil.WriteFile函数perm参数的用法

golang ioutil.WriteFile函数perm参数的用法

ioutil.WriteFile(..., perm os.FileMode)

刚开始接触golang的文件API的时候,总是纳闷为什么在创建文件的时候需要显示的指定文件的perm属性,难道不能从系统的umask里面获取吗?

实际上ioutil.WriteFile在创建新文件时,并不是直接使用参数perm的值,而是要和umask的值做合并的。把函数参数的值合并到当前umask的值,才是最终创建出来文件的perm属性。

例如

umask为空,所以ioutil.WriteFile的perm属性就是最后的文件属性

umask为0777,所以ioutil.WriteFile的perm属性全被disable掉了

umask为0000,所以ioutil.WriteFile的perm属性就是最后的文件属性

umask为0640,而ioutil.WriteFile的perm属性也是640,正好全部被关闭了,最后生成的文件没有任何属性。

即ioutil.WriteFile在写文件时,如果目标文件已经存在,那么目标文件的perm属性不会被改动,即此时ioutil.WriteFile的参数perm会被忽略。

注意一点就明白了,touch命令使用的是0666的属性,它并没有给X(executable)属性置值,所以不管在umask中对executable位是否置1,touch命令就不能生成一个具有executable的文件。

golang write 是覆盖的吗

Socket通信的原理还是比较简单的, 它大致分为以下几个步骤。 服务器端的步骤如下。 (1)建立服务器端的Socket,开始侦听整个网络中的连接请求。 (2)当检测到来自客户端的连接请求时,

golang中怎么处理socket长连接

为每个client fd开两个goroutine,一个recv,一个send。同时还有加2个channel,一个用于recv routine向逻辑主线程传送收到的数据,一个用于逻辑主线程向send goroutine传送待发送的数据,是这样的么?

实际上需要 3 个 goroutine,一个 read,一个 send,还有一个 handle。

read goroutine 读,然后写入 recevice chan。

write goroutine 把 send chan 的东西写。

handle goroutine 是 conn 的主要处理逻辑,负责把 recevice chan 的东西读出来 call 业务逻辑。

业务逻辑中要写数据就直接写入 send chan。

这样就可以保证,业务逻辑的读写都是在 handle goroutine 上处理,而避免 race 产生。

如果需要定时任务(比如心跳),就在 handle goroutine 上加上一个 timer.C;

如果需要 goroutine 下发任务,在 handle goroutine 增加一个 task chan,hanlde 收到 task 后处理业务;

如果需要输出结果,那就增加 result chan,业务逻辑把数据输出即可。

----------------------------

还有,如果我开2个goroutine的话,client断开连接了,假设recv goroutine先发生err并且close(fd),那在send goroutine中该如何处理呢?有可能不应该这样处理,那应该怎么处理呢?

如果 net.Conn Close() 了,不论 Read() 阻塞还是 Write() 阻塞都会立即收到 err 返回。

一般来说,Write() 是不可能主动知道连接断开的,除非是 SetDeadline() 猜测对方断掉了,指定时间内没有写成功就认为是断开。Read() 是可以主动收到对方发来的断开(TCP FIN),但也没办法知道异常的断开(当然也可以设置超时)。

无论是谁,是确实收到 FIN 还是 Deadline 猜测断开,只要 Close() 大家就知道连接断开了。

handle goroutine 还有一个用处就是:你的程序主动结束的时候,能正确的 close conn,让对方知道你是真的断开了,而不用去猜。

golang 结构体 字节对齐是怎么样的

用golang解析二进制协议时,其实没必要管结构体的字段的对齐规则,何况语言规范也没有规定如何对齐,也就是没有规则。用encoding/binary.Read函数直接读入struct里就行,struct就像c那样写

type Data struct {

Size, MsgType uint16

Sequence uint32

// ...

}

golang编译器加不加padding,Read都能正常工作,runtime知道Data的布局的,不像C直接做cast所以要知道怎样对齐。

用unsafe.Alignof可以知道每个field的对齐长度,但没必要用到。

package main

/*

#include stdint.h

#pragma pack(push, 1)

typedef struct {

uint16_t size;

uint16_t msgtype;

uint32_t sequnce;

uint8_t data1;

uint32_t data2;

uint16_t data3;

} mydata;

#pragma pack(pop)

mydata foo = {

1, 2, 3, 4, 5, 6,

};

int size() {

return sizeof(mydata);

}

*/

import "C"

import (

"bytes"

"encoding/binary"

"fmt"

"log"

"unsafe"

)

func main() {

bs := C.GoBytes(unsafe.Pointer(C.foo), C.size())

fmt.Printf("len %d data %v\n", len(bs), bs)

var data struct {

Size, Msytype uint16

Sequence uint32

Data1 uint8

Data2 uint32

Data3 uint16

}

err := binary.Read(bytes.NewReader(bs), binary.LittleEndian, data)

if err != nil {

log.Fatal(err)

}

fmt.Printf("%v\n", data) // {1 2 3 4 5 6}

buf := new(bytes.Buffer)

binary.Write(buf, binary.BigEndian, data)

fmt.Printf("%d %v\n", buf.Len(), buf.Bytes()) // 15 [0 1 0 2 0 0 0 3 4 0 0 0 5 0 6]

}

golang怎么通过数据流直接生成excel上传至oss

import java.io.*; import jxl.*; … … … … try { //构建Workbook对象, 只读Workbook对象 //直接从本地文件创建Workbook //从输入流创建Workbook InputStream is = new FileInputStream(sourcefile); jxl.Workbook rwb = Workbook.getWorkbook(is); } catch (Exception e) { e.printStackTrace(); } 一旦创建了Workbook,我们就可以通过它来访问Excel Sheet(术语:工作表)。参考下面的代码片段: //获取第一张Sheet表 Sheet rs = rwb.getSheet(0); 我们既可能通过Sheet的名称来访问它,也可以通过下标来访问它。如果通过下标来访问的话,要注意的一点是下标从0开始,就像数组一样。 一旦得到了Sheet,我们就可以通过它来访问Excel Cell(术语:单元格)。参考下面的代码片段: //获取第一行,第一列的值 Cell c00 = rs.getCell(0, 0); String strc00 = c00.getContents(); //获取第一行,第二列的值 Cell c10 = rs.getCell(1, 0); String strc10 = c10.getContents(); //获取第二行,第二列的值 Cell c11 = rs.getCell(1, 1); String strc11 = c11.getContents(); System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType()); System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType()); System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType()); 如果仅仅是取得Cell的值,我们可以方便地通过getContents()方法,它可以将任何类型的Cell值都作为一个字符串返回。示例代码中Cell(0, 0)是文本型,Cell(1, 0)是数字型,Cell(1,1)是日期型,通过getContents(),三种类型的返回值都是字符型。 如果有需要知道Cell内容的确切类型,API也提供了一系列的方法。参考下面的代码片段: String strc00 = null; double strc10 = 0.00; Date strc11 = null; Cell c00 = rs.getCell(0, 0); Cell c10 = rs.getCell(1, 0); Cell c11 = rs.getCell(1, 1); if(c00.getType() == CellType.LABEL) { LabelCell labelc00 = (LabelCell)c00; strc00 = labelc00.getString(); } if(c10.getType() == CellType.NUMBER) { NmberCell numc10 = (NumberCell)c10; strc10 = numc10.getValue(); } if(c11.getType() == CellType.DATE) { DateCell datec11 = (DateCell)c11; strc11 = datec11.getDate(); } System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType()); System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType()); System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType()); 在得到Cell对象后,通过getType()方法可以获得该单元格的类型,然后与API提供的基本类型相匹配,强制转换成相应的类型,最后调用相应的取值方法getXXX(),就可以得到确定类型的值。API提供了以下基本类型,与Excel的数据格式相对应,如下图所示: 每种类型的具体意义,请参见Java Excel API Document。 当你完成对Excel电子表格数据的处理后,一定要使用close()方法来关闭先前创建的对象,以释放读取数据表的过程中所占用的内存空间,在读取大量数据时显得尤为重要。参考如下代码片段: //操作完成时,关闭对象,释放占用的内存空间 rwb.close(); Java Excel API提供了许多访问Excel数据表的方法,在这里我只简要地介绍几个常用的方法,其它的方法请参考附录中的Java Excel API Document。 • Workbook类提供的方法 1. int getNumberOfSheets() 获得工作薄(Workbook)中工作表(Sheet)的个数,示例: jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); int sheets = rwb.getNumberOfSheets(); 2. Sheet[] getSheets() 返回工作薄(Workbook)中工作表(Sheet)对象数组,示例: jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); Sheet[] sheets = rwb.getSheets(); 3. String getVersion() 返回正在使用的API的版本号,好像是没什么太大的作用。 jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); String apiVersion = rwb.getVersion(); • Sheet接口提供的方法 1. String getName() 获取Sheet的名称,示例: jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); jxl.Sheet rs = rwb.getSheet(0); String sheetName = rs.getName(); 2. int getColumns() 获取Sheet表中所包含的总列数,示例: jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); jxl.Sheet rs = rwb.getSheet(0); int rsColumns = rs.getColumns(); 3. Cell[] getColumn(int column) 获取某一列的所有单元格,返回的是单元格对象数组,示例: jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); jxl.Sheet rs = rwb.getSheet(0); Cell[] cell = rs.getColumn(0); 4. int getRows() 获取Sheet表中所包含的总行数,示例: jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); jxl.Sheet rs = rwb.getSheet(0); int rsRows = rs.getRows(); 5. Cell[] getRow(int row) 获取某一行的所有单元格,返回的是单元格对象数组,示例子: jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); jxl.Sheet rs = rwb.getSheet(0); Cell[] cell = rs.getRow(0); 6. Cell getCell(int column, int row) 获取指定单元格的对象引用,需要注意的是它的两个参数,第一个是列数,第二个是行数,这与通常的行、列组合有些不同。 jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); jxl.Sheet rs = rwb.getSheet(0); Cell cell = rs.getCell(0, 0); 生成新的Excel工作薄 下面的代码主要是向大家介绍如何生成简单的Excel工作表,在这里单元格的内容是不带任何修饰的(如:字体,颜色等等),所有的内容都作为字符串写入。(完整代码见ExcelWriting.java) 与读取Excel工作表相似,首先要使用Workbook类的工厂方法创建一个可写入的工作薄(Workbook)对象,这里要注意的是,只能通过API提供的工厂方法来创建Workbook,而不能使用WritableWorkbook的构造函数,因为类WritableWorkbook的构造函数为protected类型。示例代码片段如下: import java.io.*; import jxl.*; import jxl.write.*; … … … … try { //构建Workbook对象, 只读Workbook对象 //Method 1:创建可写入的Excel工作薄 jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile)); //Method 2:将WritableWorkbook直接写入到输出流 /* OutputStream os = new FileOutputStream(targetfile); jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os); */ } catch (Exception e) { e.printStackTrace(); } API提供了两种方式来处理可写入的输出流,一种是直接生成本地文件,如果文件名不带全路径的话,缺省的文件会定位在当前目录,如果文件名带有全路径的话,则生成的Excel文件则会定位在相应的目录;另外一种是将Excel对象直接写入到输出流,例如:用户通过浏览器来访问Web服务器,如果HTTP头设置正确的话,浏览器自动调用客户端的Excel应用程序,来显示动态生成的Excel电子表格。 接下来就是要创建工作表,创建工作表的方法与创建工作薄的方法几乎一样,同样是通过工厂模式方法获得相应的对象,该方法需要两个参数,一个是工作表的名称,另一个是工作表在工作薄中的位置,参考下面的代码片段: //创建Excel工作表 jxl.write.WritableSheet ws = wwb.createSheet("Test Sheet 1", 0); "这锅也支好了,材料也准备齐全了,可以开始下锅了!",现在要做的只是实例化API所提供的Excel基本数据类型,并将它们添加到工作表中就可以了,参考下面的代码片段: //1.添加Label对象 jxl.write.Label labelC = new jxl.write.Label(0, 0, "This is a Label cell"); ws.addCell(labelC); //添加带有字型Formatting的对象 jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD, true); jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf); jxl.write.Label labelCF = new jxl.write.Label(1, 0, "This is a Label Cell", wcfF); ws.addCell(labelCF); //添加带有字体颜色Formatting的对象 jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.RED); jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc); jxl.write.Label labelCFC = new jxl.write.Label(1, 0, "This is a Label Cell", wcfFC); ws.addCell(labelCF); //2.添加Number对象 jxl.write.Number labelN = new jxl.write.Number(0, 1, 3.1415926); ws.addCell(labelN); //添加带有formatting的Number对象 jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##"); jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf); jxl.write.Number labelNF = new jxl.write.Number(1, 1, 3.1415926, wcfN); ws.addCell(labelNF); //3.添加Boolean对象 jxl.write.Boolean labelB = new jxl.write.Boolean(0, 2, false); ws.addCell(labelB); //4.添加DateTime对象 jxl.write.DateTime labelDT = new jxl.write.DateTime(0, 3, new java.util.Date()); ws.addCell(labelDT); //添加带有formatting的DateFormat对象 jxl.write.DateFormat df = new jxl.write.DateFormat("dd MM yyyy hh:mm:ss"); jxl.write.WritableCellFormat wcfDF = new jxl.write.WritableCellFormat(df); jxl.write.DateTime labelDTF = new jxl.write.DateTime(1, 3, new java.util.Date(), wcfDF); ws.addCell(labelDTF); 这里有两点大家要引起大家的注意。第一点,在构造单元格时,单元格在工作表中的位置就已经确定了。一旦创建后,单元格的位置是不能够变更的,尽管单元格的内容是可以改变的。第二点,单元格的定位是按照下面这样的规律(column, row),而且下标都是从0开始,例如,A1被存储在(0, 0),B1被存储在(1, 0)。 最后,不要忘记关闭打开的Excel工作薄对象,以释放占用的内存,参见下面的代码片段: //写入Exel工作表 wwb.write(); //关闭Excel工作薄对象 wwb.close(); 这可能与读取Excel文件的操作有少少不同,在关闭Excel对象之前,你必须要先调用write()方法,因为先前的操作都是存储在缓存中的,所以要通过该方法将操作的内容保存在文件中。如果你先关闭了Excel对象,那么只能得到一张空的工作薄了。 拷贝、更新Excel工作薄 接下来简要介绍一下如何更新一个已经存在的工作薄,主要是下面二步操作,第一步是构造只读的Excel工作薄,第二步是利用已经创建的Excel工作薄创建新的可写入的Excel工作薄,参考下面的代码片段:(完整代码见ExcelModifying.java) //创建只读的Excel工作薄的对象 jxl.Workbook rw = jxl.Workbook.getWorkbook(new File(sourcefile)); //创建可写入的Excel工作薄对象 jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile), rw); //读取第一张工作表 jxl.write.WritableSheet ws = wwb.getSheet(0); //获得第一个单元格对象 jxl.write.WritableCell wc = ws.getWritableCell(0, 0); //判断单元格的类型, 做出相应的转化 if(wc.getType() == CellType.LABEL) { Label l = (Label)wc; l.setString("The value has been modified."); } //写入Excel对象 wwb.write(); //关闭可写入的Excel对象 wwb.close(); //关闭只读的Excel对象 rw.close(); 之所以使用这种方式构建Excel对象,完全是因为效率的原因,因为上面的示例才是API的主要应用。为了提高性能,在读取工作表时,与数据相关的一些输出信息,所有的格式信息,如:字体、颜色等等,是不被处理的,因为我们的目的是获得行数据的值,既使没有了修饰,也不会对行数据的值产生什么影响。唯一的不利之处就是,在内存中会同时保存两个同样的工作表,这样当工作表体积比较大时,会占用相当大的内存,但现在好像内存的大小并不是什么关键因素了。 一旦获得了可写入的工作表对象,我们就可以对单元格对象进行更新的操作了,在这里我们不必调用API提供的add()方法,因为单元格已经于工作表当中,所以我们只需要调用相应的setXXX()方法,就可以完成更新的操作了。 尽单元格原有的格式化修饰是不能去掉的,我们还是可以将新的单元格修饰加上去,以使单元格的内容以不同的形式表现。 新生成的工作表对象是可写入的,我们除了更新原有的单元格外,还可以添加新的单元格到工作表中,这与示例2的操作是完全一样的。 最后,不要忘记调用write()方法,将更新的内容写入到文件中,然后关闭工作薄对象,这里有两个工作薄对象要关闭,一个是只读的,另外一个是可写入的。 小结 本文只是对Java Excel API中常用的方法作了介绍,要想更详尽地了解API,请大家参考API文档,或源代码。Java Excel API是一个开放源码项目,请大家关注它的最新进展,有兴趣的朋友也可以申请加入这个项目,或者是提出宝贵的意见。

Golang的垃圾回收

最近垃圾分类的话题热度一下子就上去了,很多人因为垃圾分类的问题很头痛。因为垃圾这个话题,那我就想来说说Golang里面的垃圾,于是就有了这篇博客,golang中的垃圾回收。

现阶段网上针对golang垃圾回收的解析已经很多了,所以我也没有必要仔仔细细的一点点说,还是那个原则,用最直白的话告诉你,垃圾到底是怎么收的。

首先本文后续都会使用 GC 代替垃圾回收这几个字。

我们知道创建对象会给他分配内存资源,如果这个对象不使用了,而这个内存资源却一直被占用的话,那么我们的电脑很快就会被放满,所以需要将这些垃圾对象进行回收。

要回收,那么我们必须知道什么才是垃圾,什么不是垃圾。

在我们看来,一个对象以后都不用了,就是垃圾。

在程序看来,一个对象没有被引用了,就是垃圾。

首先说明一下,下面说的停,都是STW,stop the world,全世界暂停,所有运行的都停下来了。

先告诉所有人,停一下,我来记录一下当前状态。

告诉所有人,你们继续,该干嘛干嘛,我标记一下要用的对象

一开始所有点是白色,首先从根节点出发,标记相连的点为灰色(相连证明有引用),并且将所有灰色的点存起来;

告诉所有人,再停一下,在第二个过程中,因为所有人继续在工作,那么就会产生新的垃圾,因为第一个过程记录了状态,所以需要标记一下新的垃圾;然后清除所有白色的点,因为白色的点是没人引用的,也就是垃圾。

你一定会有这样的疑问:

那么既然会导致那么多问题,为什么不直接停下来,标记完回收完了再开始呢?

因为慢~

所以这样GC的原因是既要保证GC正常执行,又要保证效率,不能停的时间太长。

其实第一次停的时候,启动了一个写屏障 (write barrier)它需要记录后续过程中新创建的对象

这个过程称为三色标记,有点类似广度优先搜索。

这次是必须停,因为在第二个过程中引用会发生变化,从而需要停止后重新扫描一遍;然后关闭写屏障,最后再清理。

开启写屏障时需要stw

关闭写屏障前需要stw

开启写屏障之后的标记过程与其他程序并发执行

关闭写屏障之后的清扫过程与其他程序并发执行

那毕竟GC还是需要STW的,虽然可能停止时间很短,但是对于程序来说,整个程序停止1秒那对于用户来说就是致命打击。所以GC肯定需要一个触发的条件,不能想来就来。

这是一个触发的条件,默认GC百分比设置的是100,意思是,如果这次回收之后总共占用2M的内存,那么下次触发的条件时当超过4M的时候;同理,当这次回收之后总共占用4M,那么下次触发条件就是8M。

这个简单,当一定时间(2分钟)没有执行过GC就触发GC

使用命令 runtime.GC() 手动触发GC

以上就是在golang中垃圾回收的大致流程,总的来说使用三色标记法进行标记清除,并且标记时与程序运行并行,为了解决问题使用写屏障来记录标记过程中对象的变更。总来的来说也是为了提高垃圾回收的效率,并且尽可能的减少STW的时间。

了解下来,与java的分代回收相比,golang中的回收算法理解起来更加简单一些。