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

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

微信又更新新功能近日,微信发布新功能,终于加入了声音锁的删除功能。因此如果你设置过微信声音锁,那么现在可以删除或者重设了。话题微信新增删除声音锁功能的消息也冲上微博热搜,引发网友们的热议。微信声音斩获信创大比武赛道大奖360走在信创实践前列近日,2022信创大比武通信业务运营技术赛道落幕,作为此次大比武活动七个赛道中唯一的通信领域赛道,吸引了众多业内顶尖运营技术厂商参与竞争,360数字安全凭借一整套完善的360安全浏河北3季报全国12强,唐山第一,石家庄逆袭,邯郸猛,房价均跌11月财经新势力河北,是我国北方一个重要的省份。这里的经济去年曾经被北京超过,今年却有所回温。2022年前三季度已经过去,河北的表现如何呢?今天我们就通过数据,一起来关注一下。看看今日全国尿素出厂价格2022年11月17日哈喽,大家好!这里是化肥价格行情!关注我每天看最新尿素复合肥磷铵钾肥价格行情!今天(2022年11月17日)下面是今日国内最新尿素价格行情!今日国内尿素涨势明显放缓,随着价格上涨一web3和web3。0有何不同?最近,你可能经常听到的一个最热门的流行语是Web3,这是GavinWood(以太坊的联合创始人)在2014年首次使用,由于一些因素,Web3这个词在2022年以来获得了更多的曝光。遥控器厂辰奕智能闯关创业板IPO夫妻店变身划江而治后卡点申报彩电行业已进入存量时代,但与之配套的遥控器企业却逆势而上意图叩响A股大门。11月18日,主要为华为等品牌提供智能遥控器代工服务的广东辰奕智能科技股份有限公司(下称辰奕智能)将迎来创给收入不高的女生,10个大胆的省钱建议我全部的野心,不过自由一生文小月亮排版小月亮俞敏洪曾说解决自卑的方式就是去赚钱,郁闷寂寞了就去赚钱,追不到喜欢的人也去赚钱,没有安全感了还是去赚钱。当你吃饱了撑的闲的空虚焦虑无聊的EmilioPucci2022秋冬系列,轻佻的活力魅力,大胆能量的乐趣EmilioPucci的这些服装之上,彩色的颜色相互结合,带来了色彩的鲜艳活力,还有不同色彩的撞色冲击,更多了一些花纹图案的气质服装结合了一些乐趣的设计,在一些轻佻的气息中,也结合漆亚林王钰涵社交机器人数字用户的建构逻辑与智能陷阱的治理路向内容提要智能传播时代,社交机器人通过积极参与网络互动实现了传播主体性的升维。作为数字用户,社交机器人通过重构意见气候拥有影响社会认知的能力作为低成本流量,机器人的流量造假增加了社会高通Arm处理器ORYON亮相巨头联手人工智能超级计算机芯闻速递两分钟了解芯片大事高通自研Arm处理器ORYON亮相高通骁龙技术峰会上,高通自研Arm指令集处理器短暂亮相。该款处理器的命名为ORYON,ORYONCPU预计明年向客户交付。此前按高性能微服务网关Apinto的本地调试背景在上一篇文章高性能API网关goku底层开发框架的设计与实现1(httpswww。toutiao。comarticle7039998811200487943)中,我们对其底层的
NASA有史以来最强大运载火箭太空发射系统将首次试飞10颗立方体卫星。图片来源CORYHUSTONNASA8月底,美国宇航局(NASA)有史以来最强大的运载火箭太空发射系统(SLS)将进行首次试飞。这枚98米高的火箭将开始为期42天紫金山天文台揭示大样本分子云稠密气体辐射的基本关系来源中国科学院决定分子云内部的稠密气体含量及分布的因素是分子云研究领域的基本问题之一。基于银河系第二象限中的18,190个12CO分子云大样本,中国科学院紫金山天文台银河画卷巡天团拒绝响应美国号召,ASML就DUV光刻机表态,芯片巨头或开始清库存此前全球芯片热,美国不断拿芯片对我们卡脖子,逼着我们国产半导体行业加速发展。随着热浪退却,美国芯片库存开始堆积,前不久有消息传出,表示其又开始想要对我们进行倾销。不过,美国一边想向美国电影安吉拉怀孕记关注后可查看更多电影信息,这里值得关注。预告片欣赏影片概况又名无豆瓣评分5。7时间2009国别美国分类喜剧片长106分钟导演BrianHerzlinger主演海瑟格拉汉姆Heath美国多米诺骨牌倒了!众多科技巨头裁员,或受经济衰退连累?在全球经济发展前景并不是十分明朗的前提下,有分析人士称苹果业绩并会不亮眼。然而苹果公司7月29日发布的第三季度财报成绩显示,截至6月25日,苹果三季度净营收829。59亿美元,与去与逝者视频聊天?美国一公司开发新技术,逝者生前可录视频生成AI形象英国每日邮报16日报道,在亲朋好友葬礼上与逝者交谈?想法可能听起来像黑镜最新一集的情节。然而一家总部位于美国洛杉矶的初创公司,开发了一种全息对话视频体验技术,可能会让这一切成为现实唤境星推官丨禁忌代入感拉满!一起找寻被隐藏的真相本文为头条号创作者唤境原创,未经允许不可转载解谜推理游戏最吸引玩家的,莫不过是成功解谜带来的成就感了。在第八期唤境激励计划中,一款叫禁忌的解谜推理游戏被评为了B级作品。究竟这款解谜珠穆朗玛峰上为什么会有海洋生物化石?电影攀登者中有这样一个镜头吴京饰演的方五洲在给学生上课时,拿出了一块三叶虫的化石,告诉学生们,这块化石是1960年中国登山队第一次攀登珠穆朗玛峰时在山顶找到的。三叶虫是远古时期的一外媒全球生物多样性面临多种威胁据合众社近日报道,一项新的研究显示,地球上所有物种面临的灭绝威胁可能比此前认为的要严重得多。此前一项生物多样性调查发现,自1500年以来,全球约有30的物种受到灭绝威胁或濒临灭绝。科学家展示新方法利用磁铁在微重力条件下从水中获取氧气科学家们展示了一种利用磁铁在微重力条件下从水中获取氧气的方法,这被描述为帮助人类进入深空的系统发展的一个关键进展。该技术作为一种具有成本效益和可行的方式,在宇航员的旅程中保持呼吸,模拟人生2。第三方NO。CC自定义蓝图x1(现代沿海别墅)资源共享此为海外Sim社区活跃创作者IDSimsArch发布的又一张蓝图,这是一栋名为寂静海浪的沙滩别墅,该蓝图和往常一样,依然为高品质兼NO。CC属性,无需任何第三方组件,只要保证你的模