先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
正文
文章目录
前言
虽然 Swift 6 已经在地平线上浮现,但 5.x 版本仍然有很多新功能-更简单的 if 和 switch 用法、宏、非可复制类型、自定义 actor 执行器等等都将在 Swift 5.9 中推出,再次带来了一个巨大的更新。
在本文中,将介绍这个版本中最重要的变化,提供代码示例和解释,以便可以自行尝试。需要在 Xcode 14 中安装最新的 Swift 5.9 工具链,或者使用 Xcode 15 beta。
Noncopyable 结构体和枚举
SE-0390 引入了无法复制的结构体和枚举的概念,从而允许在代码的多个位置共享一个结构体或枚举的单个实例,虽然只有一个所有者,但现在可以在代码的不同部分访问。
首先,此更改引入了用于取消要求的新语法:~Copyable
。这意味着 “此类型不能被复制”,并且此取消语法目前在其他地方不可用 - 例如,我们不能使用 ~Equatable
来退出类型的 ==
。
因此,我们可以像下面代码创建一个新的不可复制的 User
结构体:
struct User: ~Copyable {
var name: String
}
注意:Noncopyable 不能满足除 Sendable
之外的任何协议。
一旦创建了 User
实例,其不可复制的特性意味着它与 Swift 的先前版本不一样。例如,下面的示例代码:
func createUser() {
let newUser = User(name: "Anonymous")
var userCopy = newUser
print(userCopy.name)
}
createUser()
但是我们已经声明了 User
结构体为不可复制,也无法复制 newUser
,将 newUser
分配给 userCopy
导致原始的 newUser
值被消耗,这意味着不能使用,因为所有权现在属于 userCopy
。如果尝试将 print(userCopy.name)
更改为 print(newUser.name)
,Swift 会抛出一个编译器错误。
新的限制还适用于如何将非可复制类型用作函数参数:SE-0377 规定函数必须明确指定是打算消费值并在函数完成后使其在调用点无效,还是希望借用值以便与代码中的其他借用部分同时读取其数据。
因此,可以编写一个函数来创建用户,另一个函数来借用用户以获得只读访问其数据的权限:
func createAndGreetUser() {
let newUser = User(name: "Anonymous")
greet(newUser)
print("Goodbye, \(newUser.name)")
}
func greet(\_ user: borrowing User) {
print("Hello, \(user.name)!")
}
createAndGreetUser()
与此相反,如果我们使 greet()
函数使用 consuming User
,则 print("Goodbye, \(newUser.name)")
将不被允许 - Swift 将认为 greet()
运行后,newUser
值将无效。另一方面,由于 consuming 方法必须结束对象的生命周期,可以自由地修改其属性。
这种共享行为赋予了非可复制结构体以前仅限于类和 actor 的超能力:当对非可复制实例的最后一个引用被销毁时,可以提供自动运行的析构函数。
重要提示: 这与类上的析构函数的行为略有不同,可能是早期实现的问题或有意为之。
首先,下面是使用类的析构函数的代码示例:
class Movie {
var name: String
init(name: String) {
self.name = name
}
deinit {
print("\(name) is no longer available")
}
}
func watchMovie() {
let movie = Movie(name: "The Hunt for Red October")
print("Watching \(movie.name)")
}
watchMovie()
当运行该代码时,会先打印 “Watching The Hunt for Red October”,然后打印 “The Hunt for Red October is no longer available”。但是,如果将类型的定义从 class Movie
更改为 struct Movie: ~Copyable
,将会看到这两个 print()
语句以相反的顺序运行 - 先说电影不再可用,然后说正在观看。
非可复制类型内部的方法默认情况下是借用的,但是可以像可复制类型一样标记为 mutating
,并且还可以标记为 consuming,表示该值在方法运行后无效。
例如,我们熟悉的电影和电视剧《碟中谍》,秘密特工们通过一卷只能播放一次的自毁磁带获得任务指令。对于这样的方式,非可复制结构体非常适合:
struct MissionImpossibleMessage: ~Copyable {
private var message: String
init(message: String) {
self.message = message
}
consuming func read() {
print(message)
}
这样标记的 message 本身是私有的,因此只能通过调用消费实例的 read()
方法来访问它。
与变异方法不同,消费方法可以在类型的常量实例上运行。因此,像下面这样的代码是可以的:
func createMessage() {
let message = MissionImpossibleMessage(message: "You need to abseil down a skyscraper for some reason.")
message.read()
}
createMessage()
注意: 因为 message.read()
消费了 message
实例,所以尝试第二次调用 message.read()
将会报错。
与析构函数结合使用时,消费方法会使清理工作重复执行。例如,如果在游戏中跟踪高分,可能希望具有一个消费的 finalize()
方法,将最新的高分写入永久存储,并阻止其他人进一步更改分数,但在对象销毁时也保存最新的分数到磁盘。
为了避免这个问题,Swift 5.9 引入了一个新的 discard
操作符,可以用于非可复制类型的消费方法。在消费方法中使用 discard self
可以阻止该对象的析构函数运行。
因此,可以像这样实现 HighScore
结构:
struct HighScore: ~Copyable {
var value = 0
consuming func finalize() {
print("Saving score to disk…")
discard self
}
deinit {
print("Deinit is saving score to disk…")
}
}
func createHighScore() {
var highScore = HighScore()
highScore.value = 20
highScore.finalize()
}
createHighScore()
提示: 当运行该代码时,你会看到 deinitializer
消息被打印两次 - 一次是在更改 value
属性时,实际上销毁并重新创建了结构体,一次是在 createHighScore()
方法结束时。
在使用这个新功能时,还有一些额外的复杂性需要注意:
- 类和 actor 不能是非可复制的。
- 非可复制类型暂时不支持泛型,这排除了可选的非可复制对象和非可复制对象数组。
- 如果在另一个结构体或枚举类型中将非可复制类型用作属性,那么父结构体或枚举类型也必须是非可复制的。
- 当对现有类型添加或移除
Copyable
时需要非常小心,因为会改变用法。如果在库中发布代码,这将破坏 ABI。
结束变量绑定的生命周期
使用消耗运算符结束变量绑定的生命周期
SE-0366 扩展了对可复制类型的局部变量和常量的消耗值概念,这对于希望避免在其数据传递过程中发生不必要的保留/释放调用的开发人员可能很有益处。
最简单的形式下,消耗运算符如下所示:
struct User {
var name: String
}
func createUser() {
let newUser = User(name: "Anonymous")
let userCopy = consume newUser
print(userCopy.name)
}
createUser()
其中重要的是 let userCopy
这一行,同时执行两个操作:
- 将
newUser
的值复制到userCopy
中。 - 结束
newUser
的生命周期,因此任何进一步访问它的尝试都会引发错误。
这样可以明确告诉编译器“不允许再次使用这个值”,这将代表强制执行这个规则。
可以看到这在使用所谓的黑洞 _
时特别常见,我们不希望复制数据,而只是想将其标记为已销毁,例如:
func consumeUser() {
let newUser = User(name: "Anonymous")
\_ = consume newUser
}
实际上,最常见的情况可能是将值传递给如下的函数:
func createAndProcessUser() {
let newUser = User(name: "Anonymous")
process(user: consume newUser)
}
func process(user: User) {
print("Processing \(name)…")
}
createAndProcessUser()
有两件特别值得了解的事情。
首先,Swift 跟踪代码的哪些分支消耗了值,并有条件地强制执行规则。因此,在这段代码中,两种可能性中只有一种消耗了 User
实例:
func greetRandomly() {
let user = User(name: "Taylor Swift")
if Bool.random() {
let userCopy = consume user
print("Hello, \(userCopy.name)")
} else {
print("Greetings, \(user.name)")
}
}
greetRandomly()
其次,严格来说,consume
操作符作用于绑定而不是值。实践中,这意味着如果使用一个变量进行消耗,可以重新初始化该变量并正常使用:
func createThenRecreate() {
var user = User(name: "Roy Kent")
\_ = consume user
user = User(name: "Jamie Tartt")
print(user.name)
}
createThenRecreate()
makeStream() 方法
SE-0388 在 AsyncStream
和 AsyncThrowingStream
中添加了一个新的 makeStream()
方法,返回流本身以及其 continuation。
因此,不再需要编写以下代码:
var continuation: AsyncStream<String>.Continuation!
let stream = AsyncStream<String> { continuation = $0 }
### 最后的话
最近很多小伙伴找我要Linux学习资料,于是我翻箱倒柜,整理了一些优质资源,涵盖视频、电子书、PPT等共享给大家!
### 资料预览
给大家整理的视频资料:

给大家整理的电子书资料:

**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
713178613991)]
给大家整理的电子书资料:
[外链图片转存中...(img-axU2ptxh-1713178613992)]
**如果本文对你有帮助,欢迎点赞、收藏、转发给朋友,让我有持续创作的动力!**
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
[外链图片转存中...(img-pDXqSy5O-1713178613992)]
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**