范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Go语言核心36讲(Go语言实战与应用二十二)学习笔记

  44 | 使用os包中的API (上)
  我们今天要讲的是os代码包中的 API。这个代码包可以让我们拥有操控计算机操作系统的能力。 前导内容:os 包中的 API
  这个代码包提供的都是平台不相关的 API。那么说,什么叫平台不相关的 API 呢?
  它的意思是:这些 API 基于(或者说抽象自)操作系统,为我们使用操作系统的功能提供高层次的支持,但是,它们并不依赖于具体的操作系统。
  不论是 Linux、macOS、Windows,还是 FreeBSD、OpenBSD、Plan9,os代码包都可以为之提供统一的使用接口。这使得我们可以用同样的方式,来操纵不同的操作系统,并得到相似的结果。
  os包中的 API 主要可以帮助我们使用操作系统中的文件系统、权限系统、环境变量、系统进程以及系统信号。
  其中,操纵文件系统的 API 最为丰富。我们不但可以利用这些 API 创建和删除文件以及目录,还可以获取到它们的各种信息、修改它们的内容、改变它们的访问权限,等等。
  说到这里,就不得不提及一个非常常用的数据类型:os.File。
  从字面上来看,os.File类型代表了操作系统中的文件。但实际上,它可以代表的远不止于此。或许你已经知道,对于类 Unix 的操作系统(包括 Linux、macOS、FreeBSD 等),其中的一切都可以被看做是文件。
  除了文本文件、二进制文件、压缩文件、目录这些常见的形式之外,还有符号链接、各种物理设备(包括内置或外接的面向块或者字符的设备)、命名管道,以及套接字(也就是 socket),等等。
  因此,可以说,我们能够利用os.File类型操纵的东西太多了。不过,为了聚焦于os.File本身,同时也为了让本文讲述的内容更加通用,我们在这里主要把os.File类型应用于常规的文件。
  下面这个问题,就是以os.File类型代表的最基本内容入手。 我们今天的问题是:os.File类型都实现了哪些io包中的接口?
  这道题的 典型回答 是这样的。
  os.File类型拥有的都是指针方法,所以除了空接口之外,它本身没有实现任何接口。而它的指针类型则实现了很多io代码包中的接口。
  首先,对于io包中最核心的 3 个简单接口io.Reader、io.Writer和io.Closer,*os.File类型都实现了它们。
  其次,该类型还实现了另外的 3 个简单接口,即:io.ReaderAt、io.Seeker和io.WriterAt。
  正是因为*os.File类型实现了这些简单接口,所以它也顺便实现了io包的 9 个扩展接口中的 7 个。
  然而,由于它并没有实现简单接口io.ByteReader和io.RuneReader,所以它没有实现分别作为这两者的扩展接口的io.ByteScanner和io.RuneScanner。
  总之,os.File类型及其指针类型的值,不但可以通过各种方式读取和写入某个文件中的内容,还可以寻找并设定下一次读取或写入时的起始索引位置,另外还可以随时对文件进行关闭。
  但是,它们并不能专门地读取文件中的下一个字节,或者下一个 Unicode 字符,也不能进行任何的读回退操作。
  不过,单独读取下一个字节或字符的功能也可以通过其他方式来实现,比如,调用它的Read方法并传入适当的参数值就可以做到这一点。 问题解析
  这个问题其实在间接地问"os.File类型能够以何种方式操作文件?"我在前面的典型回答中也给出了简要的答案。
  在我进一步地说明一些细节之前,我们先来看看,怎样才能获得一个os.File类型的指针值(以下简称File值)。
  在os包中,有这样几个函数,即:Create、NewFile、Open和OpenFile。
  os.Create函数用于根据给定的路径创建一个新的文件。  它会返回一个File值和一个错误值。我们可以在该函数返回的File值之上,对相应的文件进行读操作和写操作。
  不但如此,我们使用这个函数创建的文件,对于操作系统中的所有用户来说,都是可以读和写的。
  换句话说,一旦这样的文件被创建出来,任何能够登录其所属的操作系统的用户,都可以在任意时刻读取该文件中的内容,或者向该文件写入内容。
  注意,如果在我们给予os.Create函数的路径之上,已经存在了一个文件,那么该函数会先清空现有文件中的全部内容,然后再把它作为第一个结果值返回。
  另外,os.Create函数是有可能返回非nil的错误值的。比如,如果我们给定的路径上的某一级父目录并不存在,那么该函数就会返回一个*os.PathError类型的错误值,以表示"不存在的文件或目录"。
  再来看os.NewFile函数。  该函数在被调用的时候,需要接受一个代表文件描述符的、uintptr类型的值,以及一个用于表示文件名的字符串值。
  如果我们给定的文件描述符并不是有效的,那么这个函数将会返回nil,否则,它将会返回一个代表了相应文件的File值。
  注意,不要被这个函数的名称误导了,它的功能并不是创建一个新的文件,而是依据一个已经存在的文件的描述符,来新建一个包装了该文件的File值。
  例如,我们可以像这样拿到一个包装了标准错误输出的File值: file3 := os.NewFile(uintptr(syscall.Stderr), "/dev/stderr")
  然后,通过这个File值向标准错误输出上写入一些内容: if file3 != nil {  defer file3.Close()  file3.WriteString(   "The Go language program writes the contents into stderr. ") }
  os.Open函数会打开一个文件并返回包装了该文件的File值。  然而,该函数只能以只读模式打开文件。换句话说,我们只能从该函数返回的File值中读取内容,而不能向它写入任何内容。
  如果我们调用了这个File值的任何一个写入方法,那么都将会得到一个表示了"坏的文件描述符"的错误值。实际上,我们刚刚说的只读模式,正是应用在File值所持有的文件描述符之上的。
  所谓的文件描述符,是由通常很小的非负整数代表的。它一般会由 I/O 相关的系统调用返回,并作为某个文件的一个标识存在。
  从操作系统的层面看,针对任何文件的 I/O 操作都需要用到这个文件描述符。只不过,Go 语言中的一些数据类型,为我们隐匿掉了这个描述符,如此一来我们就无需时刻关注和辨别它了(就像os.File类型这样)。
  实际上,我们在调用前文所述的os.Create函数、os.Open函数以及将会提到的os.OpenFile函数的时候,它们都会执行同一个系统调用,并且在成功之后得到这样一个文件描述符。这个文件描述符将会被储存在它们返回的File值中。
  os.File类型有一个指针方法,名叫Fd。它在被调用之后将会返回一个uintptr类型的值。这个值就代表了当前的File值所持有的那个文件描述符。
  不过,在os包中,除了NewFile函数需要用到它,它也没有什么别的用武之地了。所以,如果你操作的只是常规的文件或者目录,那么就无需特别地在意它了。
  最后,再说一下os.OpenFile函数。  这个函数其实是os.Create函数和os.Open函数的底层支持,它最为灵活。
  这个函数有 3 个参数,分别名为name、flag和perm。其中的name指代的就是文件的路径。而flag参数指的则是需要施加在文件描述符之上的模式,我在前面提到的只读模式就是这里的一个可选项。
  在 Go 语言中,这个只读模式由常量os.O_RDONLY代表,它是int类型的。当然了,这里除了只读模式之外,还有几个别的模式可选,我们稍后再细说。
  os.OpenFile函数的参数perm代表的也是模式,它的类型是os.FileMode,此类型是一个基于uint32类型的再定义类型。
  为了加以区别,我们把参数flag指代的模式叫做操作模式,而把参数perm指代的模式叫做权限模式。可以这么说,操作模式限定了操作文件的方式,而权限模式则可以控制文件的访问权限。关于权限模式的更多细节我们将在后面讨论。
  (获得 os.File 类型的指针值的几种方式)
  到这里,你需要记住的是,通过os.File类型的值,我们不但可以对文件进行读取、写入、关闭等操作,还可以设定下一次读取或写入时的起始索引位置。
  此外,os包中还有用于创建全新文件的Create函数,用于包装现存文件的NewFile函数,以及可被用来打开已存在的文件的Open函数和OpenFile函数。 package main  import ( 	"bytes" 	"fmt" 	"io" 	"os" 	"path/filepath" 	"reflect" 	"syscall" )  // ioTypes 代表了io代码包中的所有接口的反射类型。 var ioTypes = []reflect.Type{ 	reflect.TypeOf((*io.Reader)(nil)).Elem(), 	reflect.TypeOf((*io.Writer)(nil)).Elem(), 	reflect.TypeOf((*io.Closer)(nil)).Elem(),  	reflect.TypeOf((*io.ByteReader)(nil)).Elem(), 	reflect.TypeOf((*io.RuneReader)(nil)).Elem(), 	reflect.TypeOf((*io.ReaderAt)(nil)).Elem(), 	reflect.TypeOf((*io.Seeker)(nil)).Elem(), 	reflect.TypeOf((*io.WriterTo)(nil)).Elem(), 	reflect.TypeOf((*io.ByteWriter)(nil)).Elem(), 	reflect.TypeOf((*io.WriterAt)(nil)).Elem(), 	reflect.TypeOf((*io.ReaderFrom)(nil)).Elem(),  	reflect.TypeOf((*io.ByteScanner)(nil)).Elem(), 	reflect.TypeOf((*io.RuneScanner)(nil)).Elem(), 	reflect.TypeOf((*io.ReadSeeker)(nil)).Elem(), 	reflect.TypeOf((*io.ReadCloser)(nil)).Elem(), 	reflect.TypeOf((*io.WriteCloser)(nil)).Elem(), 	reflect.TypeOf((*io.WriteSeeker)(nil)).Elem(), 	reflect.TypeOf((*io.ReadWriter)(nil)).Elem(), 	reflect.TypeOf((*io.ReadWriteSeeker)(nil)).Elem(), 	reflect.TypeOf((*io.ReadWriteCloser)(nil)).Elem(), }  func main() { 	// 示例1。 	file1 := (*os.File)(nil) 	fileType := reflect.TypeOf(file1) 	var buf bytes.Buffer 	fmt.Fprintf(&buf, "Type %T implements ", file1) 	for _, t := range ioTypes { 		if fileType.Implements(t) { 			buf.WriteString(t.String()) 			buf.WriteByte(",") 			buf.WriteByte(" ") 		} 	} 	output := buf.Bytes() 	output[len(output)-2] = "." 	fmt.Printf("%s ", output)  	// 示例2。 	fileName1 := "something1.txt" 	filePath1 := filepath.Join(os.TempDir(), fileName1) 	var paths []string 	paths = append(paths, filePath1) 	dir, _ := os.Getwd() 	paths = append(paths, filepath.Join(dir[:len(dir)-1], fileName1)) 	for _, path := range paths { 		fmt.Printf("Create a file with path %s ... ", path) 		_, err := os.Create(path) 		if err != nil { 			var underlyingErr string 			if _, ok := err.(*os.PathError); ok { 				underlyingErr = "(path error)" 			} 			fmt.Printf("error: %v %s ", err, underlyingErr) 			continue 		} 		fmt.Println("The file has been created.") 	} 	fmt.Println()  	// 示例3。 	fmt.Println("New a file associated with stderr ...") 	file3 := os.NewFile(uintptr(syscall.Stderr), "/dev/stderr") 	if file3 != nil { 		file3.WriteString( 			"The Go language program writes something to stderr. ") 	} 	fmt.Println()  	// 示例4。 	fmt.Printf("Open a file with path %s ... ", filePath1) 	file4, err := os.Open(filePath1) 	if err != nil { 		fmt.Printf("error: %v ", err) 		return 	} 	fmt.Println("Write something to the file ...") 	_, err = file4.WriteString("something") 	var underlyingErr string 	if _, ok := err.(*os.PathError); ok { 		underlyingErr = "(path error)" 	} 	fmt.Printf("error: %v %s ", err, underlyingErr) 	fmt.Println()  	// 示例5。 	fmt.Printf("Open a file with path %s ... ", filePath1) 	file5a, err := os.Open(filePath1) 	if err != nil { 		fmt.Printf("error: %v ", err) 		return 	} 	fmt.Printf( 		"Is there only one file descriptor for the same file in the same process? %v ", 		file5a.Fd() == file4.Fd()) 	file5b := os.NewFile(file5a.Fd(), filePath1) 	fmt.Printf("Can the same file descriptor represent the same file? %v ", 		file5b.Name() == file5a.Name()) 	fmt.Println()  	// 示例6。 	fmt.Printf("Reuse a file on path %s ... ", filePath1) 	file6, err := os.OpenFile(filePath1, os.O_WRONLY|os.O_TRUNC, 0666) 	if err != nil { 		fmt.Printf("error: %v ", err) 		return 	} 	contents := "something" 	fmt.Printf("Write %q to the file ... ", contents) 	n, err := file6.WriteString(contents) 	if err != nil { 		fmt.Printf("error: %v ", err) 	} else { 		fmt.Printf("The number of bytes written is %d. ", n) 	} } 总结
  我们今天讲的是os代码包以及其中的程序实体。我们首先讨论了os包存在的意义,和它的主要用途。代码包中所包含的 API,都是对操作系统的某方面功能的高层次抽象,这使得我们可以通过它以统一的方式,操纵不同的操作系统,并得到相似的结果。
  在这个代码包中,操纵文件系统的 API 最为丰富,最有代表性的就是数据类型os.File。os.File类型不但可以代表操作系统中的文件,还可以代表很多其他的东西。尤其是在类 Unix 的操作系统中,它几乎可以代表一切可以操纵的软件和硬件。 笔记源码
  https://github.com/MingsonZheng/go-core-demo

威马汽车好看实用还有高科技加持转载每日话汽车相关数据显示,1月份新能源乘用车批发量达到41。1万辆,同比增长141。4。零售量达到34。7万辆,同比增长132。不可否认,入手新能源汽车已经成为大趋势了!不过,新美国黑客组织匿名者向俄罗斯宣战,发动全面的网络战争在俄罗斯对乌克兰采取全面军事行动后,国际著名黑客组织匿名者(Anonymous)在社交媒体上对俄罗斯宣战,宣布对俄罗斯政府发动网络战争。据报道,RT(今日俄罗斯)电视台此前发布消息中国在建5G工业互联网项目超过2000个中新社北京2月25日电(记者刘育英)中国互联网络信息中心(CNNIC)25日发布的第49次中国互联网络发展状况统计报告显示,2021年中国信息通信网络建设稳步推进,工业互联网取得积1月我国汽车产销量同比稳步增长新华社北京2月18日电(记者高亢)记者18日从中国汽车工业协会获悉,2022年1月,我国汽车产销量分别达242。2万辆和253。1万辆,环比分别下降16。7和9。2,同比分别增长1套现一时爽!马斯克和弟弟出售持股的交易遭调查中新经纬2月25日电据华尔街日报中文网报道,知情人士透露,美国证券交易委员会(SEC)正在调查特斯拉首席执行官马斯克和他的弟弟最近出售股票是否违反了内幕交易规则。报道称,SEC的调为何荷兰能垄断光刻机?其实技术难度堪比登天我国在芯片领域当中,除了有着很高的技术壁垒需要突破之外,而技术难度堪比登天的光刻机也同样是十分重要的,对我国的发展来说,更是起到了很大的作用,但是我国在光刻机当中的发展在研发时日之骗子横行却屹立不倒,谁能颠覆58同城?图片来源视觉中国文丨好看商业,作者丨周一围,编辑丨安心58同城再次陷入了虚假信息危机。2月16日,中国驻柬埔寨大使馆发布消息称,一名李姓中国男子,其因轻信网上的虚假招工信息,被犯罪WiFi7即将问世,网速可达40G比5G更快文BU审核子扬校对知秋近年来,传输范围更广灵活性更高的无线网络技术快速发展,大有超过有线传输的势头。如今,无线网络技术已经来到了第六代,也就是WiFi6。WiFi6火爆与上代相比,韩媒苹果混合现实头戴采用先进的microOLED显示屏据韩国ET新闻报道,苹果公司的混合现实头戴再次传言将采用先进的microOLED显示屏。microOLED显示屏可直接安装在晶片上,而不是玻璃基板上,这使得屏幕更薄更小能效更高。它造车新排位,二梯队为何成不了第一?文孙光辛2月21日,有消息称哪吒汽车近期再获20亿元D轮融资,主要投资机构包括中国中车集团旗下的中车基金和深圳市国资背景的深创投。此次融资完成后,哪吒汽车的估值上升至250亿元。哪企业的数字化水平如何分级数字化是当前毫无疑问的热词,国家在积极规划大力支持企业在跃跃欲试,差不多各个行业都在研究如何跨界,如何借数字化转型的风口,发展自己的业务。那么问题来了,一个企业的数字化的水平或效果
1分钟,查准率查全率达99以上!如何实现?图为蚂蚁集团副总裁智能科技事业群总裁蒋国飞。中国经济网记者裴小阁摄影随着人们物质生活的丰富,文化产业的发展迎来了巨大的发展机遇,同时也面临着一些挑战。蚂蚁集团副总裁智能科技事业群总和目摄像头远程视频摄像管控APP和目摄像头APP是一款非常实用的远程视频摄像管控的软件,如果想要进一步确保家中办公室等场所的财产安全,那么这款软件绝对是个不错的选择,其功能相当强大,适用于家中商铺办公室等场所,可内卷严重,不懂MyBatis插件开发怎么行,教你实现MyBatis分页插件MyBatis可谓是Java开发工程师必须要掌握的持久层框架,它能够让我们更容易的通过Java代码操作数据库,并且它还有很高的扩展性,我们可以自定义插件,去让MyBatis的功能变网络对柳传志褒贬不一你认为他是好人还是坏人?历史会证明柳传志就是历史罪人,一个披着民族企业的外衣,其实就是彻头彻尾的美国企业,为美军免费送电脑,公开资敌,投敌叛国,把全资国有企业通过自己诡异的骚操作,把联想改成自己的企业,不有人说iphone手机显示WiFi的是假手机,对吗?为什么?不知道你听谁说的,我做过相关视频,可以的话关注我查看我发过的视频即可找到。国行(中国大陆版本)外版(但不是假货只是国外版本)打开设置,看到WiFi字样只能确定它不是国行而已,没有其矿场大迁徙,几百万台矿机已迁往南北美,俄罗斯乃至中亚等地据金融时报报道,在我国于5月进行清理矿场的行动后,全球14家最大的加密货币矿场已将超过200万台矿机从我国迁出运往了其他地区。比特数码公司(BitDigital)的首席战略官Sam初生牛犊不怕虎,自古英雄出少年华为的天才少年计划依靠天才少年计划,华为取得了丰硕的科研成果。就在不久前,依靠天才少年钟钊及其团队,华为实现了全球首个AutoML大规模商用。AutoML是英文AutomatedMachineLea什么是哈希?散列是指从可变大小的输入生成固定大小的输出的过程。这是通过使用称为散列函数(作为散列算法实现)的数学公式来完成的。尽管并非所有哈希函数都涉及密码学的使用,但所谓的密码哈希函数是加密电子行业176页深度报告汽车与XR,下一个十年(报告出品方作者国泰君安,王聪,苏凌瑶,舒迪)1。可穿戴手表与XR齐飞,供应链深度受益疫情强化用户健康需求,健康运动趋势明确,随着无线技术迭代及健康设备云平台应用及服务架构持续完善怎么去水印?Ps方法一1。用ps打开需要修改的图片2。左侧工具栏中找到修复工具3。选定区域进行修复4。完成修改后找文件,导出图片方法二去除水印,也不一定非得要用ps,手机软件美图秀秀就可以。可老师上课佩带数码扩音器讲课,这样做合不合适?如果题主不是老师的话,我建议你拿本书照着念30分钟,自己亲自感受一下。相信你就会有一个明确的答案,老师上课是不是真的需要佩戴数码扩音器。因为作为一位老师来说,上课佩戴数码扩音器是非