共享软件篋hello_exercism:程序代码解释

  共享软件篋本身只能提供给其他共享篋和应用程序使用。Cargo工具实现了项目内所有目录和文件有机联系在一起。当运行测试代码或者实例代码时,这些代码都知道应该怎么样连接到正在开发的共享篋。

学习内容

  • 阐述共享篋文件功能
  • 理解项目共享篋程序代码

篇目

  1. 项目配置文件Cargo.toml
  2. 程序文件lib.rs的核心代码
  3. 静态生命周期的字符串文字类型
  4. 关键词mod与关键词pub
  5. 实例目录的单元实例文件
  6. 实例目录的集成实例文件
  7. 题外话
  8. Rust语言类型与关键词
  9. 浅谈软件篋的模块
  10. 关键词let
  11. 表达式、语句和模块
  12. 项目配置文件
  13. 参考资料

项目配置文件Cargo.toml

  文件Cargo.toml是由用户编写的描述项目共享篋依赖关系。而文件Cargo.lock包含有关共享软件篋的依赖项的确切信息。它是由Cargo工具自动生成和维护的,不应手动对其进行编辑。

# Crate Configuration File: ./Cargo.toml
[package]
name = "hello_exercism"
version = "0.5.5"
authors = ["cnruby <gudao.luo@gmail.com>"]
edition = "2018"
readme = "README.md"
license = "MIT OR Apache-2.0"
repository = "https://github.com/cnruby/learn-rust-by-crates/tree/master/hello-world"
homepage = "https://crates.io/crates/hello_exercism"
documentation = "https://cnruby.github.io/learn-rust-by-crates/hello-world/hello_exercism/"
categories = ["development-tools::testing"]
description = "how to create an own crate"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
#hello_extern = { version = "0.1.1"}
i_crate = { version = "0.1.1", package = "hello_extern"}

  在文件Cargo.toml里,最重要的一项是共享软件篋名称:name。这是使用该共享篋的入口名称。这里默认模块名称为hello_exercism。

  最常用的一节是共享篋依赖关系:[dependencies]。这里有一行依赖关系代码,说明共享篋有赖于外部共享篋。这里使用了软件篋hello_exercism的已经发布的版本,只是为了解释问题和说明方便,实际上可以依赖所有需要的共享篋。

程序文件lib.rs的核心代码

  程序文件lib.rs是由三部分代码。第一部分是共享篋核心代码:两个函数hello()和hallo()。第二部分是私有代码测试函数。第三部分是集成测试函数。这里仅仅说明该程序两个函数的功能,将在后面章节说明其它两个部分的测试代码。

  程序文件lib.rs是共享篋的入口文件。它有两个函数hello()和hallo(),其功能都是返回一个字符串文字。hello()返回英文问候,而hallo()返回德文问候。它们返回的类型也都是&'static str的字符串,这一类型是静态生命周期的字符串文字。

// Rust File: src/lib.rs
pub fn hello() -> &'static str {
    println!("{}", hallo());
    "Hello, World!"
}

fn hallo() -> &'static str {
    "Hallo, Welt!"
}

// BEGIN: unit tests for private code
// code 1
#[cfg(test)]
#[path = "./private_tests/owned_hello.rs"]
mod owned_hello;

// code 2
#[cfg(test)]
#[path = "./private_tests/mod.rs"]
mod private_tests;

// code 3
#[cfg(test)]
mod private_tests_with_use {
    use super::*;
    //use super::hallo;

    #[test]
    fn it_works_at_private() {
        assert_eq!("Hallo, Welt!", hallo());
    }
}

// code 4
#[cfg(test)]
mod private_tests_without_use {
    #[test]
    fn it_works_at_private() {
        assert_eq!("Hallo, Welt!", super::hallo());
    }
}
// END unit tests for private code 

// BEGIN: integration tests
#[cfg(test)]
#[path = "./integration_tests/i_hello.rs"]
mod i_hello;

#[cfg(test)]
#[path = "./integration_tests/mod.rs"]
mod integration_tests;
// END: integration tests

静态生命周期的字符串文字类型

  程序文件lib.rs里,两个函数的返回类型都是:静态生命周期的字符串文字类型。

  ⓡ 所有字符串文字类型都是引用,且具有静态生命周期的功能。

  ↳ 这里的函数返回值是包含一个引用字符串文字类型值,所以函数返回类型也要此类型&str。因为在整个程序过程中需要该类型是有效的,所以此类型还要增加静态生命周期'static修饰关键词。

关键词mod与关键词pub

  Ⓓ 在默认情况下,无论使用关键词mod定义的模块,还使用关键词fn定义的函数,它们都是私有的。要使得它们可公开访问的话,就需要使用修饰词关键词'pub'。

  ↳ 程序文件lib.rs里,hello()是公共可访问的函数,而hallo()只是模块hello_exercism内可访问的私有函数。该软件篋的公共接口只有:函数hello()。

  Ⓓ 共享篋模块默认是公开的。

  ↳ 这里共享篋模块名称是hello_exercism,尽管既没有关键词mod也没有关键词pub出现,但是Rust语言已经给了该模块名称这两个关键词。

实例目录的单元实例文件

  单元实例仅仅测试此软件篋自身的功能。

  ⓡ 凡是存在main()函数的Rust程序都是可执行的。

  这个程序的功能是调用了该项目的软件篋hello_exercism程序的函数hello(),且打印调用函数的结果。这也是该共享篋的功能。

  Ⓓ 在运行实例目录下可执行文件时,Cargo工具自动会调用程序lib.rs。

// Rust File: examples/u_hello.rs
fn main() {
    println!("{}", hello_exercism::hello());
}

  在共享篋里的实例目录下的可执行的Rust程序,使用下面命令执行,且得到执行结果如下:

# 从该共享篋项目的根目录执行下面命令;
$ cargo run --example u_hello -q
Hallo, Welt!
Hello, World!

实例目录的集成实例文件

  集成实例测试此共享篋与外部其它共享篋的功能。

  这个程序的功能是调用了外部软件篋hello_exercism程序的函数hello(),且打印调用函数的结果。这也是该共享篋的功能。此外,还比较了正在开发的软件篋与外部软件篋的函数返回值。

// Rust File: examples/i_hello.rs
fn main() {
    println!("{}", i_crate::hello());
    assert_eq!(hello_exercism::hello(), i_crate::hello());
}

  在共享篋里的实例目录下的可执行的Rust程序,使用下面命令执行,且得到执行结果如下:

# 从该共享篋项目的根目录执行下面命令;
$ cargo run --example i_hello -q
Hello, World!
Hallo, Welt!

题外话

Rust语言类型与关键词

  对于修饰词关键词'static',Rust语言以与常量类似的方式提供了类似“全局变量”的功能。对每一个值只有一个实例,并且位于内存中的固定位置。

  在Rust语言里,存在一类关键词是修饰词关键词,如关键词"pub"和“static”。

类型关键词类型说明
&str字符串文字
static静态修饰词关键词
'生命周期关键词
'static静态生命周期关键词
&'static str静态生命周期字符串文字

浅谈软件篋的模块

  每一个共享篋都有自己的入口模块名称,这里是hello_exercism,使用共享篋都要从这个名称开始,这里模块hello_exercism有自己的函数hello()。在程序文件lib.rs内还,可以使用关键词mod再定义模块名称,但是它们都是hello_exercism的子模块。

关键词let

  从作用意义上,共享篋的函数hello()类似于使用关键词let语句,即可把它看作为一个类型为&str的字符串文字与一个变量绑定,如下所示:

// Rust File: examples/main.rs
fn main() {
    let _: &'static str = "Hello, World!";
    let _: &str = "Hello, World!";
}

表达式、语句和模块

  在Rust语言里,表达式和语句都可以作为一行代码。要是一行代码,最后没有分号就是表达式,而有分号就是语句。表达式只有作为函数的返回值。

  表达式和语句可以汇聚成一个由{}内的代码块和由关键词fn开始的函数与方法。函数和方法可以组成一个由关键词mod开始的模块。若干个模块可以形成由关键词mod开始的父模块。

项目配置文件

  除了项目配置文件Cargo.toml之外,还可以有其它功能的配置文件,如工具rustfmt的配置文件。

参考资料