

GitHub - Jason5Lee/defer-kt: Go-inspired defer-based resource management
source link: https://github.com/Jason5Lee/defer-kt
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

defer-kt
Golang-inspired resource management library.
Add to your project
Gradle
implementation "me.jason5lee:defer:1.0.1"
Gradle Kotlin DSL
implementation("me.jason5lee:defer:1.0.1")
Example
Open two file for reading and writing, print a message before attempting to close them.
deferScope {
val f1 = File("/path/to/read-file").bufferedReader()
deferClosing(f1)
val f2 = File("/path/to/write-file").bufferedWriter()
.also { deferClosing(it) }
defer { println("Closing file ...") }
// Operating f1 and f2
}
Equivilent code using use
and try-finally
File("/path/to/read-file").bufferedReader().use { f1 ->
File("/path/to/write-file").bufferedWriter().use { f2 ->
try {
// Operating f1 and f2, with 3 indents instead of 1.
} finally {
println("Closing file ...")
}
}
}
Example of multiple resources and canceling: suppose you have many output targets, each target has a name. Now you want to implement an object that maintains multiple output target objects, which output information to the corresponding target according to the type of information. You can implement this object like this
data class Message(val type: String, ...)
class OutputTarget(name: String): Closeable {
override fun close() { ... }
fun output(message: Message) { ... }
}
class Output(vararg names: String) : Closeable {
private val outputMap: Map<String, OutputTarget>
init {
outputMap = deferScope {
val outMap = HashMap<String, OutputTarget>(names.size)
for (name in names) {
val target = OutputTarget(name)
// This defer is to close the created target when an exception is thrown
deferClosing(target)
outMap[name] = target
}
outMap.toMap().also {
cancelDefers() // cancel all defers because the construction was successful.
}
}
}
fun output(message: Message) {
outputMap[message.type]?.output(message)
}
override fun close() {
// You can use deferScope to ensure all targets are closed even if some fail.
deferScope {
for (output in outputMap.values) {
deferClosing(output)
}
}
}
}
Advantage over use
and try-finally
Compared to using the use function and try-finally, this library has the following advantages
- Less indent, especially if you have multiple resources to close.
- Easy to have a variable number of resources.
- Provide the
cancelDefer
method to transfer ownership, i.e. pass the resource to another object and let it close.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK