无struct的Rust模块声明与使用:重复声明是否必要?
Rust模块声明疑问:为何需要两次
pub mod img_util? 我编写了一个不含struct的Rust模块,当前代码结构如下:
img_util.rs:
pub mod img_util { use image::{ImageBuffer, Pixel}; use std::{fs::File, io::BufWriter}; fn get_color_type<P>() -> Result<png::ColorType, std::io::Error> where P: Pixel<Subpixel = u8>, { match <P as Pixel>::CHANNEL_COUNT { 4 => Ok(png::ColorType::Rgba), 3 => Ok(png::ColorType::Rgb), _ => Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "Incorrect color channel count / format.", )), } } fn get_dpi_header_data(dpi: u32) -> Vec<u8> { let dpm = 39.370079 * dpi as f32; let rounded_dpm = dpm.round() as u32; let mut data: Vec<u8> = Vec::new(); data.extend_from_slice(&rounded_dpm.to_be_bytes()); // Pixels per unit in X-direction. data.extend_from_slice(&rounded_dpm.to_be_bytes()); // Pixels per unit in Y-direction. data.push(1); // Indicate that meters are used as unit. data } pub fn save_png_with_dpi<P>( input_img: &ImageBuffer<P, Vec<u8>>, output_img: File, dpi: u32, ) -> Result<(), std::io::Error> where P: Pixel<Subpixel = u8>, { let w = &mut BufWriter::new(output_img); let (width, height) = input_img.dimensions(); let mut encoder = png::Encoder::new(w, width, height); encoder.set_color(get_color_type::<P>()?); encoder.set_depth(png::BitDepth::Eight); encoder.set_compression(png::Compression::Best); let data = get_dpi_header_data(dpi); let mut writer = encoder.write_header()?; writer.write_chunk(png::chunk::pHYs, data.as_slice())?; writer.write_image_data(input_img)?; Ok(()) } }
lib.rs:
pub mod img_util;
main.rs:
use visual_center::img_util::img_util; img_util::save_png_with_dpi( // arguments ).unwrap();
目前模块可以正常使用,但我困惑为何需要两次声明pub mod img_util(一次在img_util.rs中,一次在lib.rs中),想询问这是否是声明和使用无struct模块的唯一方式?
这不是必须的,你现在的写法其实是嵌套了两层模块,完全可以简化:
问题根源
你在img_util.rs里写了pub mod img_util { ... },相当于在这个文件内部又定义了一个子模块;而lib.rs里的pub mod img_util;是把整个img_util.rs作为 crate 的一级模块引入。这就导致你的函数实际位于visual_center::img_util::img_util路径下,所以使用时需要两层引用。
正确的简化写法
直接去掉img_util.rs里的外层pub mod img_util,把内容平放在文件里:
修改后的img_util.rs:
use image::{ImageBuffer, Pixel}; use std::{fs::File, io::BufWriter}; fn get_color_type<P>() -> Result<png::ColorType, std::io::Error> where P: Pixel<Subpixel = u8>, { match <P as Pixel>::CHANNEL_COUNT { 4 => Ok(png::ColorType::Rgba), 3 => Ok(png::ColorType::Rgb), _ => Err(std::io::Error::new( std::io::ErrorKind::InvalidData, "Incorrect color channel count / format.", )), } } fn get_dpi_header_data(dpi: u32) -> Vec<u8> { let dpm = 39.370079 * dpi as f32; let rounded_dpm = dpm.round() as u32; let mut data: Vec<u8> = Vec::new(); data.extend_from_slice(&rounded_dpm.to_be_bytes()); // Pixels per unit in X-direction. data.extend_from_slice(&rounded_dpm.to_be_bytes()); // Pixels per unit in Y-direction. data.push(1); // Indicate that meters are used as unit. data } pub fn save_png_with_dpi<P>( input_img: &ImageBuffer<P, Vec<u8>>, output_img: File, dpi: u32, ) -> Result<(), std::io::Error> where P: Pixel<Subpixel = u8>, { let w = &mut BufWriter::new(output_img); let (width, height) = input_img.dimensions(); let mut encoder = png::Encoder::new(w, width, height); encoder.set_color(get_color_type::<P>()?); encoder.set_depth(png::BitDepth::Eight); encoder.set_compression(png::Compression::Best); let data = get_dpi_header_data(dpi); let mut writer = encoder.write_header()?; writer.write_chunk(png::chunk::pHYs, data.as_slice())?; writer.write_image_data(input_img)?; Ok(()) }
lib.rs保持不变:
pub mod img_util;
修改后的main.rs:
// 直接引用一级模块即可 use visual_center::img_util; img_util::save_png_with_dpi( // arguments ).unwrap(); // 或者直接使用完整路径,不需要use // visual_center::img_util::save_png_with_dpi(...).unwrap();
总结
这种平级写法才是Rust模块的常规用法,不管模块里有没有struct,都不需要嵌套声明。你之前的两次pub mod是误加了内层模块定义,属于冗余写法。
内容的提问来源于stack exchange,提问作者wyc
相关产品推荐
相关产品推荐

